Bläddra i källkod

i18n(panel): migrate hardcoded panel strings to en-US and translate all locales

Surface ~400 hardcoded English labels, tooltips, placeholders, dt/divider
text, modal okText/cancelText, and Spin loading from the panel pages
(clients/groups/inbounds/nodes/settings/xray/sub/index) into
web/translation/en-US.json under existing pages.<page>.* namespaces, with
JSX swapped to t(...). Brand and protocol identifiers (TLS, MTU, SNI,
NordVPN, Cloudflare WARP, etc.) stay literal.

Sync all 12 non-English locales (ar-EG, es-ES, fa-IR, id-ID, ja-JP,
pt-BR, ru-RU, tr-TR, uk-UA, vi-VN, zh-CN, zh-TW) to match en-US's
structure and translate the 521 new key paths per locale. Every locale
file now has 1539 lines, mirroring en-US ordering.

Also remove a dead duplicate "info": "Info" key under pages.inbounds
that collided with the new pages.inbounds.info.* object.

Backend: bulk attach/detach errors in web/service/client.go now route
through logger.Warningf (so they appear under /panel/api/server/logs/)
instead of only living on the response payload.
MHSanaei 7 timmar sedan
förälder
incheckning
72b97efa8a
34 ändrade filer med 6366 tillägg och 1100 borttagningar
  1. 0 1
      frontend/src/pages/clients/BulkAttachInboundsModal.tsx
  2. 0 1
      frontend/src/pages/clients/BulkDetachInboundsModal.tsx
  3. 1 1
      frontend/src/pages/groups/GroupsPage.tsx
  4. 0 1
      frontend/src/pages/inbounds/AttachClientsModal.tsx
  5. 128 128
      frontend/src/pages/inbounds/InboundFormModal.tsx
  6. 22 22
      frontend/src/pages/inbounds/InboundInfoModal.tsx
  7. 7 7
      frontend/src/pages/inbounds/InboundsPage.tsx
  8. 1 1
      frontend/src/pages/nodes/NodesPage.tsx
  9. 24 24
      frontend/src/pages/settings/GeneralTab.tsx
  10. 1 1
      frontend/src/pages/settings/SettingsPage.tsx
  11. 15 15
      frontend/src/pages/settings/SubscriptionFormatsTab.tsx
  12. 2 2
      frontend/src/pages/settings/SubscriptionGeneralTab.tsx
  13. 12 12
      frontend/src/pages/xray/BalancerFormModal.tsx
  14. 27 25
      frontend/src/pages/xray/NordModal.tsx
  15. 135 135
      frontend/src/pages/xray/OutboundFormModal.tsx
  16. 4 4
      frontend/src/pages/xray/OutboundsTab.tsx
  17. 3 3
      frontend/src/pages/xray/RoutingTab.tsx
  18. 22 22
      frontend/src/pages/xray/RuleFormModal.tsx
  19. 30 28
      frontend/src/pages/xray/WarpModal.tsx
  20. 6 6
      frontend/src/pages/xray/XrayPage.tsx
  21. 21 9
      web/service/client.go
  22. 496 79
      web/translation/ar-EG.json
  23. 299 3
      web/translation/en-US.json
  24. 466 49
      web/translation/es-ES.json
  25. 458 88
      web/translation/fa-IR.json
  26. 448 31
      web/translation/id-ID.json
  27. 469 52
      web/translation/ja-JP.json
  28. 444 27
      web/translation/pt-BR.json
  29. 487 70
      web/translation/ru-RU.json
  30. 454 37
      web/translation/tr-TR.json
  31. 476 59
      web/translation/uk-UA.json
  32. 457 40
      web/translation/vi-VN.json
  33. 470 53
      web/translation/zh-CN.json
  34. 481 64
      web/translation/zh-TW.json

+ 0 - 1
frontend/src/pages/clients/BulkAttachInboundsModal.tsx

@@ -50,7 +50,6 @@ export default function BulkAttachInboundsModal({
       const skipped = result.skipped?.length ?? 0;
       const skipped = result.skipped?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       if (errors > 0) {
       if (errors > 0) {
-        console.error('[BulkAttach] failures:', result.errors);
         messageApi.warning(
         messageApi.warning(
           t('pages.inbounds.attachClientsResultMixed', { attached, skipped, errors }),
           t('pages.inbounds.attachClientsResultMixed', { attached, skipped, errors }),
         );
         );

+ 0 - 1
frontend/src/pages/clients/BulkDetachInboundsModal.tsx

@@ -50,7 +50,6 @@ export default function BulkDetachInboundsModal({
       const skipped = result.skipped?.length ?? 0;
       const skipped = result.skipped?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       if (errors > 0) {
       if (errors > 0) {
-        console.error('[BulkDetach] failures:', result.errors);
         messageApi.warning(
         messageApi.warning(
           t('pages.clients.detachFromInboundsResultMixed', { detached, skipped, errors }),
           t('pages.clients.detachFromInboundsResultMixed', { detached, skipped, errors }),
         );
         );

+ 1 - 1
frontend/src/pages/groups/GroupsPage.tsx

@@ -411,7 +411,7 @@ export default function GroupsPage() {
         <AppSidebar />
         <AppSidebar />
         <Layout className="content-shell">
         <Layout className="content-shell">
           <Layout.Content id="content-layout" className="content-area">
           <Layout.Content id="content-layout" className="content-area">
-            <Spin spinning={!fetched} delay={200} description="Loading…" size="large">
+            <Spin spinning={!fetched} delay={200} description={t('loading')} size="large">
               {!fetched ? (
               {!fetched ? (
                 <div className="loading-spacer" />
                 <div className="loading-spacer" />
               ) : (
               ) : (

+ 0 - 1
frontend/src/pages/inbounds/AttachClientsModal.tsx

@@ -128,7 +128,6 @@ export default function AttachClientsModal({
       const skipped = result.skipped?.length ?? 0;
       const skipped = result.skipped?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       const errors = result.errors?.length ?? 0;
       if (errors > 0) {
       if (errors > 0) {
-        console.error('[AttachClients] failures:', result.errors);
         messageApi.warning(t('pages.inbounds.attachClientsResultMixed', { attached, skipped, errors }));
         messageApi.warning(t('pages.inbounds.attachClientsResultMixed', { attached, skipped, errors }));
       } else {
       } else {
         messageApi.success(t('pages.inbounds.attachClientsResult', { attached, skipped }));
         messageApi.success(t('pages.inbounds.attachClientsResult', { attached, skipped }));

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 128 - 128
frontend/src/pages/inbounds/InboundFormModal.tsx


+ 22 - 22
frontend/src/pages/inbounds/InboundInfoModal.tsx

@@ -506,7 +506,7 @@ export default function InboundInfoModal({
           )}
           )}
           {inbound.isVlessTlsFlow && (
           {inbound.isVlessTlsFlow && (
             <tr>
             <tr>
-              <td>Flow</td>
+              <td>{t('pages.clients.flow')}</td>
               <td>
               <td>
                 {clientSettings?.flow ? <Tag>{clientSettings.flow}</Tag> : <Tag color="orange">{t('none')}</Tag>}
                 {clientSettings?.flow ? <Tag>{clientSettings.flow}</Tag> : <Tag color="orange">{t('none')}</Tag>}
               </td>
               </td>
@@ -729,18 +729,18 @@ export default function InboundInfoModal({
             )}
             )}
             {inbound.isXHTTP && (
             {inbound.isXHTTP && (
               <div className="info-row">
               <div className="info-row">
-                <dt>Mode</dt>
+                <dt>{t('pages.inbounds.info.mode')}</dt>
                 <dd><Tag>{inbound.stream?.xhttp?.mode}</Tag></dd>
                 <dd><Tag>{inbound.stream?.xhttp?.mode}</Tag></dd>
               </div>
               </div>
             )}
             )}
             {inbound.isGrpc && (
             {inbound.isGrpc && (
               <>
               <>
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>grpc serviceName</dt>
+                  <dt>{t('pages.inbounds.info.grpcServiceName')}</dt>
                   <dd><Tag className="value-tag">{inbound.serviceName}</Tag></dd>
                   <dd><Tag className="value-tag">{inbound.serviceName}</Tag></dd>
                 </div>
                 </div>
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>grpc multiMode</dt>
+                  <dt>{t('pages.inbounds.info.grpcMultiMode')}</dt>
                   <dd><Tag>{String(inbound.stream?.grpc?.multiMode)}</Tag></dd>
                   <dd><Tag>{String(inbound.stream?.grpc?.multiMode)}</Tag></dd>
                 </div>
                 </div>
               </>
               </>
@@ -805,16 +805,16 @@ export default function InboundInfoModal({
       {inbound.protocol === Protocols.TUN && inbound.settings && (
       {inbound.protocol === Protocols.TUN && inbound.settings && (
         <dl className="info-list info-list-block">
         <dl className="info-list info-list-block">
           <div className="info-row">
           <div className="info-row">
-            <dt>Interface name</dt>
+            <dt>{t('pages.inbounds.info.interfaceName')}</dt>
             <dd><Tag color="green" className="value-tag">{inbound.settings.name as string}</Tag></dd>
             <dd><Tag color="green" className="value-tag">{inbound.settings.name as string}</Tag></dd>
           </div>
           </div>
           <div className="info-row">
           <div className="info-row">
-            <dt>MTU</dt>
+            <dt>{t('pages.inbounds.info.mtu')}</dt>
             <dd><Tag color="green">{inbound.settings.mtu as number}</Tag></dd>
             <dd><Tag color="green">{inbound.settings.mtu as number}</Tag></dd>
           </div>
           </div>
           {Array.isArray(inbound.settings.gateway) && (inbound.settings.gateway as string[]).length > 0 && (
           {Array.isArray(inbound.settings.gateway) && (inbound.settings.gateway as string[]).length > 0 && (
             <div className="info-row">
             <div className="info-row">
-              <dt>Gateway</dt>
+              <dt>{t('pages.inbounds.info.gateway')}</dt>
               <dd>
               <dd>
                 {(inbound.settings.gateway as string[]).map((ip, j) => (
                 {(inbound.settings.gateway as string[]).map((ip, j) => (
                   <Tag key={`tun-gw-${j}`} color="green" className="value-tag">{ip}</Tag>
                   <Tag key={`tun-gw-${j}`} color="green" className="value-tag">{ip}</Tag>
@@ -824,7 +824,7 @@ export default function InboundInfoModal({
           )}
           )}
           {Array.isArray(inbound.settings.dns) && (inbound.settings.dns as string[]).length > 0 && (
           {Array.isArray(inbound.settings.dns) && (inbound.settings.dns as string[]).length > 0 && (
             <div className="info-row">
             <div className="info-row">
-              <dt>DNS</dt>
+              <dt>{t('pages.inbounds.info.dns')}</dt>
               <dd>
               <dd>
                 {(inbound.settings.dns as string[]).map((ip, j) => (
                 {(inbound.settings.dns as string[]).map((ip, j) => (
                   <Tag key={`tun-dns-${j}`} color="green">{ip}</Tag>
                   <Tag key={`tun-dns-${j}`} color="green">{ip}</Tag>
@@ -833,12 +833,12 @@ export default function InboundInfoModal({
             </div>
             </div>
           )}
           )}
           <div className="info-row">
           <div className="info-row">
-            <dt>Outbounds interface</dt>
+            <dt>{t('pages.inbounds.info.outboundsInterface')}</dt>
             <dd><Tag color="green">{(inbound.settings.autoOutboundsInterface as string) || 'auto'}</Tag></dd>
             <dd><Tag color="green">{(inbound.settings.autoOutboundsInterface as string) || 'auto'}</Tag></dd>
           </div>
           </div>
           {Array.isArray(inbound.settings.autoSystemRoutingTable) && (inbound.settings.autoSystemRoutingTable as string[]).length > 0 && (
           {Array.isArray(inbound.settings.autoSystemRoutingTable) && (inbound.settings.autoSystemRoutingTable as string[]).length > 0 && (
             <div className="info-row">
             <div className="info-row">
-              <dt>Auto system routes</dt>
+              <dt>{t('pages.inbounds.info.autoSystemRoutes')}</dt>
               <dd>
               <dd>
                 {(inbound.settings.autoSystemRoutingTable as string[]).map((cidr, j) => (
                 {(inbound.settings.autoSystemRoutingTable as string[]).map((cidr, j) => (
                   <Tag key={`tun-rt-${j}`} color="green">{cidr}</Tag>
                   <Tag key={`tun-rt-${j}`} color="green">{cidr}</Tag>
@@ -864,7 +864,7 @@ export default function InboundInfoModal({
             <dd><Tag color="green">{inbound.settings.allowedNetwork as string}</Tag></dd>
             <dd><Tag color="green">{inbound.settings.allowedNetwork as string}</Tag></dd>
           </div>
           </div>
           <div className="info-row">
           <div className="info-row">
-            <dt>FollowRedirect</dt>
+            <dt>{t('pages.inbounds.info.followRedirect')}</dt>
             <dd>
             <dd>
               <Tag color={inbound.settings.followRedirect ? 'green' : 'red'}>
               <Tag color={inbound.settings.followRedirect ? 'green' : 'red'}>
                 {inbound.settings.followRedirect ? t('enabled') : t('disabled')}
                 {inbound.settings.followRedirect ? t('enabled') : t('disabled')}
@@ -877,7 +877,7 @@ export default function InboundInfoModal({
       {dbInbound.isMixed && inbound.settings && (
       {dbInbound.isMixed && inbound.settings && (
         <dl className="info-list info-list-block">
         <dl className="info-list info-list-block">
           <div className="info-row">
           <div className="info-row">
-            <dt>Auth</dt>
+            <dt>{t('pages.inbounds.info.auth')}</dt>
             <dd>
             <dd>
               <Tag color={inbound.settings.auth === 'password' ? 'green' : 'orange'}>
               <Tag color={inbound.settings.auth === 'password' ? 'green' : 'orange'}>
                 {inbound.settings.auth as string}
                 {inbound.settings.auth as string}
@@ -969,19 +969,19 @@ export default function InboundInfoModal({
         <>
         <>
           <dl className="info-list info-list-block">
           <dl className="info-list info-list-block">
             <div className="info-row">
             <div className="info-row">
-              <dt>Secret key</dt>
+              <dt>{t('pages.xray.wireguard.secretKey')}</dt>
               <dd><Tag className="value-tag">{inbound.settings.secretKey as string}</Tag></dd>
               <dd><Tag className="value-tag">{inbound.settings.secretKey as string}</Tag></dd>
             </div>
             </div>
             <div className="info-row">
             <div className="info-row">
-              <dt>Public key</dt>
+              <dt>{t('pages.xray.wireguard.publicKey')}</dt>
               <dd><Tag className="value-tag">{inbound.settings.pubKey as string}</Tag></dd>
               <dd><Tag className="value-tag">{inbound.settings.pubKey as string}</Tag></dd>
             </div>
             </div>
             <div className="info-row">
             <div className="info-row">
-              <dt>MTU</dt>
+              <dt>{t('pages.inbounds.info.mtu')}</dt>
               <dd><Tag>{inbound.settings.mtu as number}</Tag></dd>
               <dd><Tag>{inbound.settings.mtu as number}</Tag></dd>
             </div>
             </div>
             <div className="info-row">
             <div className="info-row">
-              <dt>No-kernel TUN</dt>
+              <dt>{t('pages.inbounds.info.noKernelTun')}</dt>
               <dd>
               <dd>
                 <Tag color={inbound.settings.noKernelTun ? 'green' : 'default'}>
                 <Tag color={inbound.settings.noKernelTun ? 'green' : 'default'}>
                   {String(inbound.settings.noKernelTun)}
                   {String(inbound.settings.noKernelTun)}
@@ -991,14 +991,14 @@ export default function InboundInfoModal({
           </dl>
           </dl>
           {Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => (
           {Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => (
             <Fragment key={idx}>
             <Fragment key={idx}>
-              <Divider>Peer {idx + 1}</Divider>
+              <Divider>{t('pages.inbounds.info.peerNumber', { n: idx + 1 })}</Divider>
               <dl className="info-list info-list-block">
               <dl className="info-list info-list-block">
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>Secret key</dt>
+                  <dt>{t('pages.xray.wireguard.secretKey')}</dt>
                   <dd><Tag className="value-tag">{peer.privateKey}</Tag></dd>
                   <dd><Tag className="value-tag">{peer.privateKey}</Tag></dd>
                 </div>
                 </div>
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>Public key</dt>
+                  <dt>{t('pages.xray.wireguard.publicKey')}</dt>
                   <dd><Tag className="value-tag">{peer.publicKey}</Tag></dd>
                   <dd><Tag className="value-tag">{peer.publicKey}</Tag></dd>
                 </div>
                 </div>
                 <div className="info-row">
                 <div className="info-row">
@@ -1006,7 +1006,7 @@ export default function InboundInfoModal({
                   <dd><Tag className="value-tag">{peer.psk}</Tag></dd>
                   <dd><Tag className="value-tag">{peer.psk}</Tag></dd>
                 </div>
                 </div>
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>Allowed IPs</dt>
+                  <dt>{t('pages.xray.wireguard.allowedIPs')}</dt>
                   <dd>
                   <dd>
                     {(peer.allowedIPs || []).map((ip, j) => (
                     {(peer.allowedIPs || []).map((ip, j) => (
                       <Tag key={`wg-ip-${idx}-${j}`} className="value-tag">{ip}</Tag>
                       <Tag key={`wg-ip-${idx}-${j}`} className="value-tag">{ip}</Tag>
@@ -1014,14 +1014,14 @@ export default function InboundInfoModal({
                   </dd>
                   </dd>
                 </div>
                 </div>
                 <div className="info-row">
                 <div className="info-row">
-                  <dt>Keep alive</dt>
+                  <dt>{t('pages.inbounds.info.keepAlive')}</dt>
                   <dd><Tag>{peer.keepAlive}</Tag></dd>
                   <dd><Tag>{peer.keepAlive}</Tag></dd>
                 </div>
                 </div>
               </dl>
               </dl>
               {wireguardConfigs[idx] && (
               {wireguardConfigs[idx] && (
                 <div className="link-panel">
                 <div className="link-panel">
                   <div className="link-panel-header">
                   <div className="link-panel-header">
-                    <Tag color="green">Peer {idx + 1} config</Tag>
+                    <Tag color="green">{t('pages.inbounds.info.peerNumberConfig', { n: idx + 1 })}</Tag>
                     <Tooltip title={t('copy')}>
                     <Tooltip title={t('copy')}>
                       <Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardConfigs[idx], t)} />
                       <Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardConfigs[idx], t)} />
                     </Tooltip>
                     </Tooltip>

+ 7 - 7
frontend/src/pages/inbounds/InboundsPage.tsx

@@ -171,7 +171,7 @@ export default function InboundsPage() {
     confirm: (value: string) => Promise<boolean | void> | boolean | void;
     confirm: (value: string) => Promise<boolean | void> | boolean | void;
   }) => {
   }) => {
     setPromptTitle(opts.title);
     setPromptTitle(opts.title);
-    setPromptOkText(opts.okText || 'OK');
+    setPromptOkText(opts.okText || t('confirm'));
     setPromptType(opts.type || 'textarea');
     setPromptType(opts.type || 'textarea');
     setPromptInitial(opts.value || '');
     setPromptInitial(opts.value || '');
     setPromptHandler(() => opts.confirm);
     setPromptHandler(() => opts.confirm);
@@ -316,8 +316,8 @@ export default function InboundsPage() {
 
 
   const importInbound = useCallback(() => {
   const importInbound = useCallback(() => {
     openPrompt({
     openPrompt({
-      title: 'Import inbound',
-      okText: 'Import',
+      title: t('pages.inbounds.importInbound'),
+      okText: t('pages.inbounds.import'),
       type: 'textarea',
       type: 'textarea',
       value: '',
       value: '',
       confirm: async (value) => {
       confirm: async (value) => {
@@ -434,9 +434,9 @@ export default function InboundsPage() {
       case 'subs': exportAllSubs(); break;
       case 'subs': exportAllSubs(); break;
       case 'resetInbounds':
       case 'resetInbounds':
         modal.confirm({
         modal.confirm({
-          title: 'Reset all inbound traffic?',
-          okText: 'Reset',
-          cancelText: 'Cancel',
+          title: t('pages.inbounds.resetAllTrafficTitle'),
+          okText: t('reset'),
+          cancelText: t('cancel'),
           onOk: async () => {
           onOk: async () => {
             const msg = await HttpUtil.post('/panel/api/inbounds/resetAllTraffics');
             const msg = await HttpUtil.post('/panel/api/inbounds/resetAllTraffics');
             if (msg?.success) await refresh();
             if (msg?.success) await refresh();
@@ -518,7 +518,7 @@ export default function InboundsPage() {
 
 
         <Layout className="content-shell">
         <Layout className="content-shell">
           <Layout.Content id="content-layout" className="content-area">
           <Layout.Content id="content-layout" className="content-area">
-            <Spin spinning={!fetched} delay={200} description="Loading…" size="large">
+            <Spin spinning={!fetched} delay={200} description={t('loading')} size="large">
               {!fetched ? (
               {!fetched ? (
                 <div className="loading-spacer" />
                 <div className="loading-spacer" />
               ) : (
               ) : (

+ 1 - 1
frontend/src/pages/nodes/NodesPage.tsx

@@ -97,7 +97,7 @@ export default function NodesPage() {
 
 
         <Layout className="content-shell">
         <Layout className="content-shell">
           <Layout.Content id="content-layout" className="content-area">
           <Layout.Content id="content-layout" className="content-area">
-            <Spin spinning={!fetched} delay={200} description="Loading…" size="large">
+            <Spin spinning={!fetched} delay={200} description={t('loading')} size="large">
               {!fetched ? (
               {!fetched ? (
                 <div className="loading-spacer" />
                 <div className="loading-spacer" />
               ) : (
               ) : (

+ 24 - 24
frontend/src/pages/settings/GeneralTab.tsx

@@ -160,8 +160,8 @@ export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProp
 
 
             <SettingListItem
             <SettingListItem
               paddings="small"
               paddings="small"
-              title="Trusted proxy CIDRs"
-              description="Comma-separated IPs/CIDRs allowed to set forwarded host, proto, and client IP headers."
+              title={t('pages.settings.trustedProxyCidrs')}
+              description={t('pages.settings.trustedProxyCidrsDesc')}
             >
             >
               <Input
               <Input
                 value={allSetting.trustedProxyCIDRs}
                 value={allSetting.trustedProxyCIDRs}
@@ -271,58 +271,58 @@ export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProp
         label: 'LDAP',
         label: 'LDAP',
         children: (
         children: (
           <>
           <>
-            <SettingListItem paddings="small" title="Enable LDAP sync">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.enable')}>
               <Switch checked={allSetting.ldapEnable} onChange={(v) => updateSetting({ ldapEnable: v })} />
               <Switch checked={allSetting.ldapEnable} onChange={(v) => updateSetting({ ldapEnable: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="LDAP host">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.host')}>
               <Input value={allSetting.ldapHost} onChange={(e) => updateSetting({ ldapHost: e.target.value })} />
               <Input value={allSetting.ldapHost} onChange={(e) => updateSetting({ ldapHost: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="LDAP port">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.port')}>
               <InputNumber value={allSetting.ldapPort} min={1} max={65535} style={{ width: '100%' }}
               <InputNumber value={allSetting.ldapPort} min={1} max={65535} style={{ width: '100%' }}
                 onChange={(v) => updateSetting({ ldapPort: Number(v) || 0 })} />
                 onChange={(v) => updateSetting({ ldapPort: Number(v) || 0 })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Use TLS (LDAPS)">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.useTls')}>
               <Switch checked={allSetting.ldapUseTLS} onChange={(v) => updateSetting({ ldapUseTLS: v })} />
               <Switch checked={allSetting.ldapUseTLS} onChange={(v) => updateSetting({ ldapUseTLS: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Bind DN">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.bindDn')}>
               <Input value={allSetting.ldapBindDN} onChange={(e) => updateSetting({ ldapBindDN: e.target.value })} />
               <Input value={allSetting.ldapBindDN} onChange={(e) => updateSetting({ ldapBindDN: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
             <SettingListItem
             <SettingListItem
               paddings="small"
               paddings="small"
               title={t('password')}
               title={t('password')}
-              description={allSetting.hasLdapPassword ? 'Configured; leave blank to keep current password.' : 'Not configured.'}
+              description={allSetting.hasLdapPassword ? t('pages.settings.ldap.passwordConfigured') : t('pages.settings.ldap.passwordUnconfigured')}
             >
             >
               <Input.Password
               <Input.Password
                 value={allSetting.ldapPassword}
                 value={allSetting.ldapPassword}
-                placeholder={allSetting.hasLdapPassword ? 'Configured - enter a new value to replace' : ''}
+                placeholder={allSetting.hasLdapPassword ? t('pages.settings.ldap.passwordPlaceholder') : ''}
                 onChange={(e) => updateSetting({ ldapPassword: e.target.value })}
                 onChange={(e) => updateSetting({ ldapPassword: e.target.value })}
               />
               />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Base DN">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.baseDn')}>
               <Input value={allSetting.ldapBaseDN} onChange={(e) => updateSetting({ ldapBaseDN: e.target.value })} />
               <Input value={allSetting.ldapBaseDN} onChange={(e) => updateSetting({ ldapBaseDN: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="User filter">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.userFilter')}>
               <Input value={allSetting.ldapUserFilter} onChange={(e) => updateSetting({ ldapUserFilter: e.target.value })} />
               <Input value={allSetting.ldapUserFilter} onChange={(e) => updateSetting({ ldapUserFilter: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="User attribute (username/email)">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.userAttr')}>
               <Input value={allSetting.ldapUserAttr} onChange={(e) => updateSetting({ ldapUserAttr: e.target.value })} />
               <Input value={allSetting.ldapUserAttr} onChange={(e) => updateSetting({ ldapUserAttr: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="VLESS flag attribute">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.vlessField')}>
               <Input value={allSetting.ldapVlessField} onChange={(e) => updateSetting({ ldapVlessField: e.target.value })} />
               <Input value={allSetting.ldapVlessField} onChange={(e) => updateSetting({ ldapVlessField: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Generic flag attribute (optional)" description="If set, overrides VLESS flag — e.g. shadowInactive.">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.flagField')} description={t('pages.settings.ldap.flagFieldDesc')}>
               <Input value={allSetting.ldapFlagField} onChange={(e) => updateSetting({ ldapFlagField: e.target.value })} />
               <Input value={allSetting.ldapFlagField} onChange={(e) => updateSetting({ ldapFlagField: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Truthy values" description="Comma-separated; default: true,1,yes,on">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.truthyValues')} description={t('pages.settings.ldap.truthyValuesDesc')}>
               <Input value={allSetting.ldapTruthyValues} onChange={(e) => updateSetting({ ldapTruthyValues: e.target.value })} />
               <Input value={allSetting.ldapTruthyValues} onChange={(e) => updateSetting({ ldapTruthyValues: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Invert flag" description="Enable when the attribute means disabled (e.g. shadowInactive).">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.invertFlag')} description={t('pages.settings.ldap.invertFlagDesc')}>
               <Switch checked={allSetting.ldapInvertFlag} onChange={(v) => updateSetting({ ldapInvertFlag: v })} />
               <Switch checked={allSetting.ldapInvertFlag} onChange={(v) => updateSetting({ ldapInvertFlag: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Sync schedule" description="Cron-like string, e.g. @every 1m">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.syncSchedule')} description={t('pages.settings.ldap.syncScheduleDesc')}>
               <Input value={allSetting.ldapSyncCron} onChange={(e) => updateSetting({ ldapSyncCron: e.target.value })} />
               <Input value={allSetting.ldapSyncCron} onChange={(e) => updateSetting({ ldapSyncCron: e.target.value })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Inbound tags" description="Inbounds that LDAP sync may auto-create or auto-delete clients on.">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.inboundTags')} description={t('pages.settings.ldap.inboundTagsDesc')}>
               <>
               <>
                 <Select
                 <Select
                   mode="multiple"
                   mode="multiple"
@@ -332,25 +332,25 @@ export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProp
                   options={inboundOptions}
                   options={inboundOptions}
                 />
                 />
                 {inboundOptions.length === 0 && (
                 {inboundOptions.length === 0 && (
-                  <div className="ldap-no-inbounds">No inbounds found. Create one in Inbounds first.</div>
+                  <div className="ldap-no-inbounds">{t('pages.settings.ldap.noInbounds')}</div>
                 )}
                 )}
               </>
               </>
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Auto create clients">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.autoCreate')}>
               <Switch checked={allSetting.ldapAutoCreate} onChange={(v) => updateSetting({ ldapAutoCreate: v })} />
               <Switch checked={allSetting.ldapAutoCreate} onChange={(v) => updateSetting({ ldapAutoCreate: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Auto delete clients">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.autoDelete')}>
               <Switch checked={allSetting.ldapAutoDelete} onChange={(v) => updateSetting({ ldapAutoDelete: v })} />
               <Switch checked={allSetting.ldapAutoDelete} onChange={(v) => updateSetting({ ldapAutoDelete: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Default total (GB)">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.defaultTotalGb')}>
               <InputNumber value={allSetting.ldapDefaultTotalGB} min={0} style={{ width: '100%' }}
               <InputNumber value={allSetting.ldapDefaultTotalGB} min={0} style={{ width: '100%' }}
                 onChange={(v) => updateSetting({ ldapDefaultTotalGB: Number(v) || 0 })} />
                 onChange={(v) => updateSetting({ ldapDefaultTotalGB: Number(v) || 0 })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Default expiry (days)">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.defaultExpiryDays')}>
               <InputNumber value={allSetting.ldapDefaultExpiryDays} min={0} style={{ width: '100%' }}
               <InputNumber value={allSetting.ldapDefaultExpiryDays} min={0} style={{ width: '100%' }}
                 onChange={(v) => updateSetting({ ldapDefaultExpiryDays: Number(v) || 0 })} />
                 onChange={(v) => updateSetting({ ldapDefaultExpiryDays: Number(v) || 0 })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Default IP limit">
+            <SettingListItem paddings="small" title={t('pages.settings.ldap.defaultIpLimit')}>
               <InputNumber value={allSetting.ldapDefaultLimitIP} min={0} style={{ width: '100%' }}
               <InputNumber value={allSetting.ldapDefaultLimitIP} min={0} style={{ width: '100%' }}
                 onChange={(v) => updateSetting({ ldapDefaultLimitIP: Number(v) || 0 })} />
                 onChange={(v) => updateSetting({ ldapDefaultLimitIP: Number(v) || 0 })} />
             </SettingListItem>
             </SettingListItem>

+ 1 - 1
frontend/src/pages/settings/SettingsPage.tsx

@@ -284,7 +284,7 @@ export default function SettingsPage() {
 
 
         <Layout className="content-shell">
         <Layout className="content-shell">
           <Layout.Content id="content-layout" className="content-area">
           <Layout.Content id="content-layout" className="content-area">
-            <Spin spinning={spinning || !fetched} delay={200} description="Loading…" size="large">
+            <Spin spinning={spinning || !fetched} delay={200} description={t('loading')} size="large">
               {!fetched ? (
               {!fetched ? (
                 <div className="loading-spacer" />
                 <div className="loading-spacer" />
               ) : (
               ) : (

+ 15 - 15
frontend/src/pages/settings/SubscriptionFormatsTab.tsx

@@ -264,19 +264,19 @@ export default function SubscriptionFormatsTab({ allSetting, updateSetting }: Su
                     label: t('pages.settings.fragmentSett'),
                     label: t('pages.settings.fragmentSett'),
                     children: (
                     children: (
                       <>
                       <>
-                        <SettingListItem paddings="small" title="Packets">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.packets')}>
                           <Input value={fragmentObj.packets} placeholder="1-1 | 1-3 | tlshello | …"
                           <Input value={fragmentObj.packets} placeholder="1-1 | 1-3 | tlshello | …"
                             onChange={(e) => setFragmentField('packets', e.target.value)} />
                             onChange={(e) => setFragmentField('packets', e.target.value)} />
                         </SettingListItem>
                         </SettingListItem>
-                        <SettingListItem paddings="small" title="Length">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.length')}>
                           <Input value={fragmentObj.length} placeholder="100-200"
                           <Input value={fragmentObj.length} placeholder="100-200"
                             onChange={(e) => setFragmentField('length', e.target.value)} />
                             onChange={(e) => setFragmentField('length', e.target.value)} />
                         </SettingListItem>
                         </SettingListItem>
-                        <SettingListItem paddings="small" title="Interval">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.interval')}>
                           <Input value={fragmentObj.interval} placeholder="10-20"
                           <Input value={fragmentObj.interval} placeholder="10-20"
                             onChange={(e) => setFragmentField('interval', e.target.value)} />
                             onChange={(e) => setFragmentField('interval', e.target.value)} />
                         </SettingListItem>
                         </SettingListItem>
-                        <SettingListItem paddings="small" title="Max split">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.maxSplit')}>
                           <Input value={fragmentObj.maxSplit} placeholder="300-400"
                           <Input value={fragmentObj.maxSplit} placeholder="300-400"
                             onChange={(e) => setFragmentField('maxSplit', e.target.value)} />
                             onChange={(e) => setFragmentField('maxSplit', e.target.value)} />
                         </SettingListItem>
                         </SettingListItem>
@@ -291,20 +291,20 @@ export default function SubscriptionFormatsTab({ allSetting, updateSetting }: Su
       },
       },
       {
       {
         key: '3',
         key: '3',
-        label: 'Noises',
+        label: t('pages.settings.subFormats.noises'),
         children: (
         children: (
           <>
           <>
-            <SettingListItem paddings="small" title="Noises" description={t('pages.settings.noisesDesc')}>
+            <SettingListItem paddings="small" title={t('pages.settings.subFormats.noises')} description={t('pages.settings.noisesDesc')}>
               <Switch checked={noisesEnabled} onChange={setNoisesEnabled} />
               <Switch checked={noisesEnabled} onChange={setNoisesEnabled} />
             </SettingListItem>
             </SettingListItem>
             {noisesEnabled && (
             {noisesEnabled && (
               <div className="nested-block">
               <div className="nested-block">
                 <Collapse items={noisesArray.map((noise, index) => ({
                 <Collapse items={noisesArray.map((noise, index) => ({
                   key: String(index),
                   key: String(index),
-                  label: `Noise №${index + 1}`,
+                  label: t('pages.settings.subFormats.noiseItem', { n: index + 1 }),
                   children: (
                   children: (
                     <>
                     <>
-                      <SettingListItem paddings="small" title="Type">
+                      <SettingListItem paddings="small" title={t('pages.settings.subFormats.type')}>
                         <Select
                         <Select
                           value={noise.type}
                           value={noise.type}
                           style={{ width: '100%' }}
                           style={{ width: '100%' }}
@@ -312,15 +312,15 @@ export default function SubscriptionFormatsTab({ allSetting, updateSetting }: Su
                           options={['rand', 'base64', 'str', 'hex'].map((p) => ({ value: p, label: p }))}
                           options={['rand', 'base64', 'str', 'hex'].map((p) => ({ value: p, label: p }))}
                         />
                         />
                       </SettingListItem>
                       </SettingListItem>
-                      <SettingListItem paddings="small" title="Packet">
+                      <SettingListItem paddings="small" title={t('pages.settings.subFormats.packet')}>
                         <Input value={noise.packet} placeholder="5-10"
                         <Input value={noise.packet} placeholder="5-10"
                           onChange={(e) => updateNoiseField(index, 'packet', e.target.value)} />
                           onChange={(e) => updateNoiseField(index, 'packet', e.target.value)} />
                       </SettingListItem>
                       </SettingListItem>
-                      <SettingListItem paddings="small" title="Delay (ms)">
+                      <SettingListItem paddings="small" title={t('pages.settings.subFormats.delayMs')}>
                         <Input value={noise.delay} placeholder="10-20"
                         <Input value={noise.delay} placeholder="10-20"
                           onChange={(e) => updateNoiseField(index, 'delay', e.target.value)} />
                           onChange={(e) => updateNoiseField(index, 'delay', e.target.value)} />
                       </SettingListItem>
                       </SettingListItem>
-                      <SettingListItem paddings="small" title="Apply to">
+                      <SettingListItem paddings="small" title={t('pages.settings.subFormats.applyTo')}>
                         <Select
                         <Select
                           value={noise.applyTo}
                           value={noise.applyTo}
                           style={{ width: '100%' }}
                           style={{ width: '100%' }}
@@ -338,7 +338,7 @@ export default function SubscriptionFormatsTab({ allSetting, updateSetting }: Su
                     </>
                     </>
                   ),
                   ),
                 }))} />
                 }))} />
-                <Button type="primary" style={{ marginTop: 10 }} onClick={addNoise}>+ Noise</Button>
+                <Button type="primary" style={{ marginTop: 10 }} onClick={addNoise}>{t('pages.settings.subFormats.addNoise')}</Button>
               </div>
               </div>
             )}
             )}
           </>
           </>
@@ -360,15 +360,15 @@ export default function SubscriptionFormatsTab({ allSetting, updateSetting }: Su
                     label: t('pages.settings.muxSett'),
                     label: t('pages.settings.muxSett'),
                     children: (
                     children: (
                       <>
                       <>
-                        <SettingListItem paddings="small" title="Concurrency">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.concurrency')}>
                           <InputNumber value={muxObj.concurrency} min={-1} max={1024} style={{ width: '100%' }}
                           <InputNumber value={muxObj.concurrency} min={-1} max={1024} style={{ width: '100%' }}
                             onChange={(v) => setMuxField('concurrency', Number(v) || 0)} />
                             onChange={(v) => setMuxField('concurrency', Number(v) || 0)} />
                         </SettingListItem>
                         </SettingListItem>
-                        <SettingListItem paddings="small" title="xudp concurrency">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.xudpConcurrency')}>
                           <InputNumber value={muxObj.xudpConcurrency} min={-1} max={1024} style={{ width: '100%' }}
                           <InputNumber value={muxObj.xudpConcurrency} min={-1} max={1024} style={{ width: '100%' }}
                             onChange={(v) => setMuxField('xudpConcurrency', Number(v) || 0)} />
                             onChange={(v) => setMuxField('xudpConcurrency', Number(v) || 0)} />
                         </SettingListItem>
                         </SettingListItem>
-                        <SettingListItem paddings="small" title="xudp UDP 443">
+                        <SettingListItem paddings="small" title={t('pages.settings.subFormats.xudpUdp443')}>
                           <Select
                           <Select
                             value={muxObj.xudpProxyUDP443}
                             value={muxObj.xudpProxyUDP443}
                             style={{ width: '100%' }}
                             style={{ width: '100%' }}

+ 2 - 2
frontend/src/pages/settings/SubscriptionGeneralTab.tsx

@@ -33,10 +33,10 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
             <SettingListItem paddings="small" title={t('pages.settings.subEnable')} description={t('pages.settings.subEnableDesc')}>
             <SettingListItem paddings="small" title={t('pages.settings.subEnable')} description={t('pages.settings.subEnableDesc')}>
               <Switch checked={allSetting.subEnable} onChange={(v) => updateSetting({ subEnable: v })} />
               <Switch checked={allSetting.subEnable} onChange={(v) => updateSetting({ subEnable: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="JSON subscription" description={t('pages.settings.subJsonEnable')}>
+            <SettingListItem paddings="small" title={t('pages.settings.subJsonEnableTitle')} description={t('pages.settings.subJsonEnable')}>
               <Switch checked={allSetting.subJsonEnable} onChange={(v) => updateSetting({ subJsonEnable: v })} />
               <Switch checked={allSetting.subJsonEnable} onChange={(v) => updateSetting({ subJsonEnable: v })} />
             </SettingListItem>
             </SettingListItem>
-            <SettingListItem paddings="small" title="Clash / Mihomo subscription">
+            <SettingListItem paddings="small" title={t('pages.settings.subClashEnableTitle')}>
               <Switch checked={allSetting.subClashEnable} onChange={(v) => updateSetting({ subClashEnable: v })} />
               <Switch checked={allSetting.subClashEnable} onChange={(v) => updateSetting({ subClashEnable: v })} />
             </SettingListItem>
             </SettingListItem>
             <SettingListItem paddings="small" title={t('pages.settings.subListen')} description={t('pages.settings.subListenDesc')}>
             <SettingListItem paddings="small" title={t('pages.settings.subListen')} description={t('pages.settings.subListenDesc')}>

+ 12 - 12
frontend/src/pages/xray/BalancerFormModal.tsx

@@ -135,19 +135,19 @@ export default function BalancerFormModal({
     >
     >
       <Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 14 } }}>
       <Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 14 } }}>
         <Form.Item
         <Form.Item
-          label="Tag"
+          label={t('pages.xray.balancer.tag')}
           required
           required
           validateStatus={issues.tag ? 'error' : duplicateTag ? 'warning' : ''}
           validateStatus={issues.tag ? 'error' : duplicateTag ? 'warning' : ''}
-          help={issues.tag || (duplicateTag ? 'Tag already used by another balancer' : '')}
+          help={issues.tag || (duplicateTag ? t('pages.xray.balancer.tagDuplicate') : '')}
           hasFeedback
           hasFeedback
         >
         >
           <Input
           <Input
             value={state.tag}
             value={state.tag}
             onChange={(e) => update('tag', e.target.value)}
             onChange={(e) => update('tag', e.target.value)}
-            placeholder="unique balancer tag"
+            placeholder={t('pages.xray.balancer.tagPlaceholder')}
           />
           />
         </Form.Item>
         </Form.Item>
-        <Form.Item label="Strategy">
+        <Form.Item label={t('pages.xray.balancer.balancerStrategy')}>
           <Select
           <Select
             value={state.strategy}
             value={state.strategy}
             onChange={(v) => update('strategy', v)}
             onChange={(v) => update('strategy', v)}
@@ -155,7 +155,7 @@ export default function BalancerFormModal({
           />
           />
         </Form.Item>
         </Form.Item>
         <Form.Item
         <Form.Item
-          label="Selector"
+          label={t('pages.xray.balancer.selector')}
           required
           required
           validateStatus={issues.selector ? 'error' : ''}
           validateStatus={issues.selector ? 'error' : ''}
           help={issues.selector || ''}
           help={issues.selector || ''}
@@ -169,7 +169,7 @@ export default function BalancerFormModal({
             options={outboundTags.map((tg) => ({ value: tg, label: tg }))}
             options={outboundTags.map((tg) => ({ value: tg, label: tg }))}
           />
           />
         </Form.Item>
         </Form.Item>
-        <Form.Item label="Fallback">
+        <Form.Item label={t('pages.xray.balancer.fallback')}>
           <Select
           <Select
             value={state.fallbackTag}
             value={state.fallbackTag}
             onChange={(v) => update('fallbackTag', v ?? '')}
             onChange={(v) => update('fallbackTag', v ?? '')}
@@ -180,23 +180,23 @@ export default function BalancerFormModal({
 
 
         {state.strategy === 'leastLoad' && (
         {state.strategy === 'leastLoad' && (
           <>
           <>
-            <Form.Item label="Expected">
+            <Form.Item label={t('pages.xray.balancer.expected')}>
               <InputNumber
               <InputNumber
                 value={settings?.expected}
                 value={settings?.expected}
                 onChange={(v) => updateSetting('expected', typeof v === 'number' ? v : undefined)}
                 onChange={(v) => updateSetting('expected', typeof v === 'number' ? v : undefined)}
                 min={0}
                 min={0}
-                placeholder="optimal node count"
+                placeholder={t('pages.xray.balancer.expectedPlaceholder')}
                 style={{ width: '100%' }}
                 style={{ width: '100%' }}
               />
               />
             </Form.Item>
             </Form.Item>
-            <Form.Item label="Max RTT">
+            <Form.Item label={t('pages.xray.balancer.maxRtt')}>
               <Input
               <Input
                 value={settings?.maxRTT ?? ''}
                 value={settings?.maxRTT ?? ''}
                 onChange={(e) => updateSetting('maxRTT', e.target.value || undefined)}
                 onChange={(e) => updateSetting('maxRTT', e.target.value || undefined)}
                 placeholder="e.g. 1s"
                 placeholder="e.g. 1s"
               />
               />
             </Form.Item>
             </Form.Item>
-            <Form.Item label="Tolerance">
+            <Form.Item label={t('pages.xray.balancer.tolerance')}>
               <InputNumber
               <InputNumber
                 value={settings?.tolerance}
                 value={settings?.tolerance}
                 onChange={(v) => updateSetting('tolerance', typeof v === 'number' ? v : undefined)}
                 onChange={(v) => updateSetting('tolerance', typeof v === 'number' ? v : undefined)}
@@ -207,7 +207,7 @@ export default function BalancerFormModal({
                 style={{ width: '100%' }}
                 style={{ width: '100%' }}
               />
               />
             </Form.Item>
             </Form.Item>
-            <Form.Item label="Baselines">
+            <Form.Item label={t('pages.xray.balancer.baselines')}>
               <Button
               <Button
                 size="small"
                 size="small"
                 type="primary"
                 type="primary"
@@ -227,7 +227,7 @@ export default function BalancerFormModal({
                 </Space.Compact>
                 </Space.Compact>
               ))}
               ))}
             </Form.Item>
             </Form.Item>
-            <Form.Item label="Costs">
+            <Form.Item label={t('pages.xray.balancer.costs')}>
               <Button
               <Button
                 size="small"
                 size="small"
                 type="primary"
                 type="primary"

+ 27 - 25
frontend/src/pages/xray/NordModal.tsx

@@ -1,4 +1,5 @@
 import { useCallback, useEffect, useMemo, useState } from 'react';
 import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 import { Button, Divider, Form, Input, message, Modal, Select, Tabs, Tag } from 'antd';
 import { Button, Divider, Form, Input, message, Modal, Select, Tabs, Tag } from 'antd';
 import { LoginOutlined, SaveOutlined } from '@ant-design/icons';
 import { LoginOutlined, SaveOutlined } from '@ant-design/icons';
 
 
@@ -58,6 +59,7 @@ export default function NordModal({
   onRemoveOutbound,
   onRemoveOutbound,
   onRemoveRoutingRules,
   onRemoveRoutingRules,
 }: NordModalProps) {
 }: NordModalProps) {
+  const { t } = useTranslation();
   const [messageApi, messageContextHolder] = message.useMessage();
   const [messageApi, messageContextHolder] = message.useMessage();
   const [loading, setLoading] = useState(false);
   const [loading, setLoading] = useState(false);
   const [nordData, setNordData] = useState<NordData | null>(null);
   const [nordData, setNordData] = useState<NordData | null>(null);
@@ -185,7 +187,7 @@ export default function NordModal({
         })
         })
         .sort((a: NordServer, b: NordServer) => a.load - b.load);
         .sort((a: NordServer, b: NordServer) => a.load - b.load);
       setServers(next);
       setServers(next);
-      if (next.length === 0) messageApi.warning('No servers found for the selected country');
+      if (next.length === 0) messageApi.warning(t('pages.xray.nord.noServers'));
     } finally {
     } finally {
       setLoading(false);
       setLoading(false);
     }
     }
@@ -197,7 +199,7 @@ export default function NordModal({
     const tech = server.technologies?.find((tt) => tt.id === 35);
     const tech = server.technologies?.find((tt) => tt.id === 35);
     const publicKey = tech?.metadata?.find((m) => m.name === 'public_key')?.value;
     const publicKey = tech?.metadata?.find((m) => m.name === 'public_key')?.value;
     if (!publicKey) {
     if (!publicKey) {
-      messageApi.error('Selected server does not advertise a NordLynx public key.');
+      messageApi.error(t('pages.xray.nord.noPublicKey'));
       return null;
       return null;
     }
     }
     return {
     return {
@@ -216,7 +218,7 @@ export default function NordModal({
     const ob = buildNordOutbound();
     const ob = buildNordOutbound();
     if (!ob) return;
     if (!ob) return;
     onAddOutbound(ob);
     onAddOutbound(ob);
-    messageApi.success('NordVPN outbound added');
+    messageApi.success(t('pages.xray.nord.outboundAdded'));
     onClose();
     onClose();
   }
   }
 
 
@@ -231,7 +233,7 @@ export default function NordModal({
       oldTag,
       oldTag,
       newTag: ob.tag as string,
       newTag: ob.tag as string,
     });
     });
-    messageApi.success('NordVPN outbound updated');
+    messageApi.success(t('pages.xray.nord.outboundUpdated'));
     onClose();
     onClose();
   }
   }
 
 
@@ -245,7 +247,7 @@ export default function NordModal({
           items={[
           items={[
             {
             {
               key: 'token',
               key: 'token',
-              label: 'Access token',
+              label: t('pages.xray.nord.accessToken'),
               children: (
               children: (
                 <Form
                 <Form
                   colon={false}
                   colon={false}
@@ -253,14 +255,14 @@ export default function NordModal({
                   wrapperCol={{ md: { span: 18 } }}
                   wrapperCol={{ md: { span: 18 } }}
                   className="mt-20"
                   className="mt-20"
                 >
                 >
-                  <Form.Item label="Access token">
+                  <Form.Item label={t('pages.xray.nord.accessToken')}>
                     <Input
                     <Input
                       value={token}
                       value={token}
-                      placeholder="Access token"
+                      placeholder={t('pages.xray.nord.accessToken')}
                       onChange={(e) => setToken(e.target.value)}
                       onChange={(e) => setToken(e.target.value)}
                     />
                     />
                     <Button type="primary" className="mt-10" loading={loading} icon={<LoginOutlined />} onClick={login}>
                     <Button type="primary" className="mt-10" loading={loading} icon={<LoginOutlined />} onClick={login}>
-                      Login
+                      {t('login')}
                     </Button>
                     </Button>
                   </Form.Item>
                   </Form.Item>
                 </Form>
                 </Form>
@@ -268,7 +270,7 @@ export default function NordModal({
             },
             },
             {
             {
               key: 'key',
               key: 'key',
-              label: 'Private key',
+              label: t('pages.xray.nord.privateKey'),
               children: (
               children: (
                 <Form
                 <Form
                   colon={false}
                   colon={false}
@@ -276,14 +278,14 @@ export default function NordModal({
                   wrapperCol={{ md: { span: 18 } }}
                   wrapperCol={{ md: { span: 18 } }}
                   className="mt-20"
                   className="mt-20"
                 >
                 >
-                  <Form.Item label="Private key">
+                  <Form.Item label={t('pages.xray.nord.privateKey')}>
                     <Input
                     <Input
                       value={manualKey}
                       value={manualKey}
-                      placeholder="Private key"
+                      placeholder={t('pages.xray.nord.privateKey')}
                       onChange={(e) => setManualKey(e.target.value)}
                       onChange={(e) => setManualKey(e.target.value)}
                     />
                     />
                     <Button type="primary" className="mt-10" loading={loading} icon={<SaveOutlined />} onClick={saveKey}>
                     <Button type="primary" className="mt-10" loading={loading} icon={<SaveOutlined />} onClick={saveKey}>
-                      Save
+                      {t('save')}
                     </Button>
                     </Button>
                   </Form.Item>
                   </Form.Item>
                 </Form>
                 </Form>
@@ -297,25 +299,25 @@ export default function NordModal({
             <tbody>
             <tbody>
               {nordData.token && (
               {nordData.token && (
                 <tr className="row-odd">
                 <tr className="row-odd">
-                  <td>Access token</td>
+                  <td>{t('pages.xray.nord.accessToken')}</td>
                   <td>{nordData.token}</td>
                   <td>{nordData.token}</td>
                 </tr>
                 </tr>
               )}
               )}
               <tr>
               <tr>
-                <td>Private key</td>
+                <td>{t('pages.xray.nord.privateKey')}</td>
                 <td>{nordData.private_key}</td>
                 <td>{nordData.private_key}</td>
               </tr>
               </tr>
             </tbody>
             </tbody>
           </table>
           </table>
 
 
           <Button loading={loading} type="primary" danger className="mt-8" onClick={logout}>
           <Button loading={loading} type="primary" danger className="mt-8" onClick={logout}>
-            Logout
+            {t('logout')}
           </Button>
           </Button>
 
 
-          <Divider className="zero-margin">Settings</Divider>
+          <Divider className="zero-margin">{t('pages.xray.warp.settings')}</Divider>
 
 
           <Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 18 } }} className="mt-10">
           <Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 18 } }} className="mt-10">
-            <Form.Item label="Country">
+            <Form.Item label={t('pages.xray.outbound.country')}>
               <Select
               <Select
                 value={countryId ?? undefined}
                 value={countryId ?? undefined}
                 showSearch={{ optionFilterProp: 'label' }}
                 showSearch={{ optionFilterProp: 'label' }}
@@ -328,18 +330,18 @@ export default function NordModal({
             </Form.Item>
             </Form.Item>
 
 
             {cities.length > 0 && (
             {cities.length > 0 && (
-              <Form.Item label="City">
+              <Form.Item label={t('pages.xray.outbound.city')}>
                 <Select
                 <Select
                   value={cityId}
                   value={cityId}
                   showSearch={{ optionFilterProp: 'label' }}
                   showSearch={{ optionFilterProp: 'label' }}
                   onChange={setCityId}
                   onChange={setCityId}
-                  options={[{ value: null, label: 'All cities' }, ...cities.map((c) => ({ value: c.id, label: c.name }))]}
+                  options={[{ value: null, label: t('pages.xray.outbound.allCities') }, ...cities.map((c) => ({ value: c.id, label: c.name }))]}
                 />
                 />
               </Form.Item>
               </Form.Item>
             )}
             )}
 
 
             {filteredServers.length > 0 && (
             {filteredServers.length > 0 && (
-              <Form.Item label="Server">
+              <Form.Item label={t('pages.xray.outbound.server')}>
                 <Select
                 <Select
                   value={serverId}
                   value={serverId}
                   showSearch={{ optionFilterProp: 'label' }}
                   showSearch={{ optionFilterProp: 'label' }}
@@ -363,17 +365,17 @@ export default function NordModal({
             )}
             )}
           </Form>
           </Form>
 
 
-          <Divider className="my-10">Outbound status</Divider>
+          <Divider className="my-10">{t('pages.xray.outbound.outboundStatus')}</Divider>
           {nordOutboundIndex >= 0 ? (
           {nordOutboundIndex >= 0 ? (
             <>
             <>
-              <Tag color="green">Enabled</Tag>
+              <Tag color="green">{t('enabled')}</Tag>
               <Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
               <Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
-                Reset
+                {t('reset')}
               </Button>
               </Button>
             </>
             </>
           ) : (
           ) : (
             <>
             <>
-              <Tag color="orange">Disabled</Tag>
+              <Tag color="orange">{t('disabled')}</Tag>
               <Button
               <Button
                 type="primary"
                 type="primary"
                 className="ml-8"
                 className="ml-8"
@@ -381,7 +383,7 @@ export default function NordModal({
                 loading={loading}
                 loading={loading}
                 onClick={addOutbound}
                 onClick={addOutbound}
               >
               >
-                Add outbound
+                {t('pages.xray.warp.addOutbound')}
               </Button>
               </Button>
             </>
             </>
           )}
           )}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 135 - 135
frontend/src/pages/xray/OutboundFormModal.tsx


+ 4 - 4
frontend/src/pages/xray/OutboundsTab.tsx

@@ -258,7 +258,7 @@ export default function OutboundsTab({
         ),
         ),
       },
       },
       {
       {
-        title: 'Tag',
+        title: t('pages.xray.outbound.tag'),
         key: 'identity',
         key: 'identity',
         align: 'left',
         align: 'left',
         render: (_v, record) => (
         render: (_v, record) => (
@@ -316,7 +316,7 @@ export default function OutboundsTab({
         },
         },
       },
       },
       {
       {
-        title: 'Latency',
+        title: t('pages.nodes.latency'),
         key: 'testResult',
         key: 'testResult',
         align: 'left',
         align: 'left',
         width: 140,
         width: 140,
@@ -398,14 +398,14 @@ export default function OutboundsTab({
           </Col>
           </Col>
           <Col xs={24} sm={12} className="toolbar-right">
           <Col xs={24} sm={12} className="toolbar-right">
             <Space size="small" wrap>
             <Space size="small" wrap>
-              <Tooltip title="TCP: fast dial-only probe. HTTP: full request through xray.">
+              <Tooltip title={t('pages.xray.outbound.testModeTooltip')}>
                 <Radio.Group value={testMode} onChange={(e) => setTestMode(e.target.value)} buttonStyle="solid" size="small">
                 <Radio.Group value={testMode} onChange={(e) => setTestMode(e.target.value)} buttonStyle="solid" size="small">
                   <Radio.Button value="tcp">TCP</Radio.Button>
                   <Radio.Button value="tcp">TCP</Radio.Button>
                   <Radio.Button value="http">HTTP</Radio.Button>
                   <Radio.Button value="http">HTTP</Radio.Button>
                 </Radio.Group>
                 </Radio.Group>
               </Tooltip>
               </Tooltip>
               <Button type="primary" loading={testingAll} icon={<PlayCircleOutlined />} onClick={() => onTestAll(testMode)}>
               <Button type="primary" loading={testingAll} icon={<PlayCircleOutlined />} onClick={() => onTestAll(testMode)}>
-                {!isMobile && 'Test all'}
+                {!isMobile && t('pages.xray.outbound.testAll')}
               </Button>
               </Button>
               <Popconfirm
               <Popconfirm
                 placement="topRight"
                 placement="topRight"

+ 3 - 3
frontend/src/pages/xray/RoutingTab.tsx

@@ -293,7 +293,7 @@ export default function RoutingTab({
           <div className="action-cell">
           <div className="action-cell">
             <HolderOutlined
             <HolderOutlined
               className="drag-handle"
               className="drag-handle"
-              title="Drag to reorder"
+              title={t('pages.xray.routing.dragToReorder')}
               onPointerDown={(ev: React.PointerEvent) => onHandlePointerDown(index, ev)}
               onPointerDown={(ev: React.PointerEvent) => onHandlePointerDown(index, ev)}
             />
             />
             <span className="row-index">{index + 1}</span>
             <span className="row-index">{index + 1}</span>
@@ -326,7 +326,7 @@ export default function RoutingTab({
         ),
         ),
       },
       },
       {
       {
-        title: 'Source',
+        title: t('pages.xray.rules.source'),
         align: 'left',
         align: 'left',
         width: 180,
         width: 180,
         key: 'source',
         key: 'source',
@@ -354,7 +354,7 @@ export default function RoutingTab({
         ),
         ),
       },
       },
       {
       {
-        title: 'Destination',
+        title: t('pages.xray.rules.dest'),
         align: 'left',
         align: 'left',
         key: 'destination',
         key: 'destination',
         render: (_v, record) => (
         render: (_v, record) => (

+ 22 - 22
frontend/src/pages/xray/RuleFormModal.tsx

@@ -148,8 +148,8 @@ export default function RuleFormModal({
       <Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 14 } }}>
       <Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 14 } }}>
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              Source IPs <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('pages.xray.ruleForm.sourceIps')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
@@ -158,8 +158,8 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              Source port <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('pages.xray.ruleForm.sourcePort')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
@@ -168,15 +168,15 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              VLESS route <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('pages.xray.ruleForm.vlessRoute')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
           <Input value={form.vlessRoute} onChange={(e) => update('vlessRoute', e.target.value)} placeholder="53,443,1000-2000" />
           <Input value={form.vlessRoute} onChange={(e) => update('vlessRoute', e.target.value)} placeholder="53,443,1000-2000" />
         </Form.Item>
         </Form.Item>
 
 
-        <Form.Item label="Network">
+        <Form.Item label={t('pages.inbounds.network')}>
           <Select
           <Select
             value={form.network}
             value={form.network}
             onChange={(v) => update('network', v)}
             onChange={(v) => update('network', v)}
@@ -184,7 +184,7 @@ export default function RuleFormModal({
           />
           />
         </Form.Item>
         </Form.Item>
 
 
-        <Form.Item label="Protocol">
+        <Form.Item label={t('pages.inbounds.protocol')}>
           <Select
           <Select
             mode="multiple"
             mode="multiple"
             value={form.protocol}
             value={form.protocol}
@@ -193,7 +193,7 @@ export default function RuleFormModal({
           />
           />
         </Form.Item>
         </Form.Item>
 
 
-        <Form.Item label="Attributes">
+        <Form.Item label={t('pages.xray.ruleForm.attributes')}>
           <Button size="small" icon={<PlusOutlined />} onClick={() => update('attrs', [...form.attrs, ['', '']])} />
           <Button size="small" icon={<PlusOutlined />} onClick={() => update('attrs', [...form.attrs, ['', '']])} />
         </Form.Item>
         </Form.Item>
         <Form.Item wrapperCol={{ span: 24 }}>
         <Form.Item wrapperCol={{ span: 24 }}>
@@ -202,7 +202,7 @@ export default function RuleFormModal({
               <InputAddon>{`${idx + 1}`}</InputAddon>
               <InputAddon>{`${idx + 1}`}</InputAddon>
               <Input
               <Input
                 value={attr[0]}
                 value={attr[0]}
-                placeholder="Name"
+                placeholder={t('pages.nodes.name')}
                 onChange={(e) => {
                 onChange={(e) => {
                   const next = form.attrs.map((a, i) => (i === idx ? ([e.target.value, a[1]] as [string, string]) : a));
                   const next = form.attrs.map((a, i) => (i === idx ? ([e.target.value, a[1]] as [string, string]) : a));
                   update('attrs', next);
                   update('attrs', next);
@@ -210,7 +210,7 @@ export default function RuleFormModal({
               />
               />
               <Input
               <Input
                 value={attr[1]}
                 value={attr[1]}
-                placeholder="Value"
+                placeholder={t('pages.xray.ruleForm.value')}
                 onChange={(e) => {
                 onChange={(e) => {
                   const next = form.attrs.map((a, i) => (i === idx ? ([a[0], e.target.value] as [string, string]) : a));
                   const next = form.attrs.map((a, i) => (i === idx ? ([a[0], e.target.value] as [string, string]) : a));
                   update('attrs', next);
                   update('attrs', next);
@@ -226,7 +226,7 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
+            <Tooltip title={t('pages.xray.rules.useComma')}>
               IP <QuestionCircleOutlined />
               IP <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
@@ -236,8 +236,8 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              Domain <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('domainName')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
@@ -246,8 +246,8 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              User <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('pages.xray.ruleForm.user')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
@@ -256,15 +256,15 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Comma-separated list">
-              Port <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.rules.useComma')}>
+              {t('pages.inbounds.port')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >
           <Input value={form.port} onChange={(e) => update('port', e.target.value)} placeholder="53,443,1000-2000" />
           <Input value={form.port} onChange={(e) => update('port', e.target.value)} placeholder="53,443,1000-2000" />
         </Form.Item>
         </Form.Item>
 
 
-        <Form.Item label="Inbound tags">
+        <Form.Item label={t('pages.xray.ruleForm.inboundTags')}>
           <Select
           <Select
             mode="multiple"
             mode="multiple"
             value={form.inboundTag}
             value={form.inboundTag}
@@ -273,7 +273,7 @@ export default function RuleFormModal({
           />
           />
         </Form.Item>
         </Form.Item>
 
 
-        <Form.Item label="Outbound tag">
+        <Form.Item label={t('pages.xray.ruleForm.outboundTag')}>
           <Select
           <Select
             value={form.outboundTag}
             value={form.outboundTag}
             onChange={(v) => update('outboundTag', v)}
             onChange={(v) => update('outboundTag', v)}
@@ -283,8 +283,8 @@ export default function RuleFormModal({
 
 
         <Form.Item
         <Form.Item
           label={
           label={
-            <Tooltip title="Routes traffic through one of the configured load balancers">
-              Balancer tag <QuestionCircleOutlined />
+            <Tooltip title={t('pages.xray.ruleForm.balancerTagTooltip')}>
+              {t('pages.xray.ruleForm.balancerTag')} <QuestionCircleOutlined />
             </Tooltip>
             </Tooltip>
           }
           }
         >
         >

+ 30 - 28
frontend/src/pages/xray/WarpModal.tsx

@@ -1,4 +1,5 @@
 import { useCallback, useEffect, useMemo, useState } from 'react';
 import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 import {
 import {
   Alert,
   Alert,
   Button,
   Button,
@@ -72,6 +73,7 @@ export default function WarpModal({
   onResetOutbound,
   onResetOutbound,
   onRemoveOutbound,
   onRemoveOutbound,
 }: WarpModalProps) {
 }: WarpModalProps) {
+  const { t } = useTranslation();
   const [messageApi, messageContextHolder] = message.useMessage();
   const [messageApi, messageContextHolder] = message.useMessage();
   const [loading, setLoading] = useState(false);
   const [loading, setLoading] = useState(false);
   const [warpData, setWarpData] = useState<WarpData | null>(null);
   const [warpData, setWarpData] = useState<WarpData | null>(null);
@@ -167,7 +169,7 @@ export default function WarpModal({
         setWarpConfig(null);
         setWarpConfig(null);
         setWarpPlus('');
         setWarpPlus('');
       } else {
       } else {
-        setLicenseError(msg?.msg || 'Failed to set WARP license.');
+        setLicenseError(msg?.msg || t('pages.xray.warp.licenseError'));
       }
       }
     } finally {
     } finally {
       setLoading(false);
       setLoading(false);
@@ -192,7 +194,7 @@ export default function WarpModal({
 
 
   function addOutbound() {
   function addOutbound() {
     if (!stagedOutbound) {
     if (!stagedOutbound) {
-      messageApi.warning('Fetch the WARP config first.');
+      messageApi.warning(t('pages.xray.warp.fetchFirst'));
       return;
       return;
     }
     }
     onAddOutbound(stagedOutbound);
     onAddOutbound(stagedOutbound);
@@ -213,49 +215,49 @@ export default function WarpModal({
       <Modal open={open} title="Cloudflare WARP" footer={null} onCancel={onClose}>
       <Modal open={open} title="Cloudflare WARP" footer={null} onCancel={onClose}>
       {!hasWarp ? (
       {!hasWarp ? (
         <Button type="primary" loading={loading} icon={<ApiOutlined />} onClick={register}>
         <Button type="primary" loading={loading} icon={<ApiOutlined />} onClick={register}>
-          Create WARP account
+          {t('pages.xray.warp.createAccount')}
         </Button>
         </Button>
       ) : (
       ) : (
         <>
         <>
           <table className="warp-data-table">
           <table className="warp-data-table">
             <tbody>
             <tbody>
               <tr className="row-odd">
               <tr className="row-odd">
-                <td>Access token</td>
+                <td>{t('pages.xray.warp.accessToken')}</td>
                 <td>{warpData?.access_token}</td>
                 <td>{warpData?.access_token}</td>
               </tr>
               </tr>
               <tr>
               <tr>
-                <td>Device ID</td>
+                <td>{t('pages.xray.warp.deviceId')}</td>
                 <td>{warpData?.device_id}</td>
                 <td>{warpData?.device_id}</td>
               </tr>
               </tr>
               <tr className="row-odd">
               <tr className="row-odd">
-                <td>License key</td>
+                <td>{t('pages.xray.warp.licenseKey')}</td>
                 <td>{warpData?.license_key}</td>
                 <td>{warpData?.license_key}</td>
               </tr>
               </tr>
               <tr>
               <tr>
-                <td>Private key</td>
+                <td>{t('pages.xray.warp.privateKey')}</td>
                 <td>{warpData?.private_key}</td>
                 <td>{warpData?.private_key}</td>
               </tr>
               </tr>
             </tbody>
             </tbody>
           </table>
           </table>
 
 
           <Button loading={loading} type="primary" danger className="mt-8" icon={<DeleteOutlined />} onClick={delConfig}>
           <Button loading={loading} type="primary" danger className="mt-8" icon={<DeleteOutlined />} onClick={delConfig}>
-            Delete account
+            {t('pages.xray.warp.deleteAccount')}
           </Button>
           </Button>
 
 
-          <Divider className="zero-margin">Settings</Divider>
+          <Divider className="zero-margin">{t('pages.xray.warp.settings')}</Divider>
 
 
           <Collapse
           <Collapse
             className="my-10"
             className="my-10"
             items={[
             items={[
               {
               {
                 key: '1',
                 key: '1',
-                label: 'WARP / WARP+ license key',
+                label: t('pages.xray.warp.licenseKeyLabel'),
                 children: (
                 children: (
                   <Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 14 } }}>
                   <Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 14 } }}>
-                    <Form.Item label="Key">
+                    <Form.Item label={t('pages.xray.warp.key')}>
                       <Input
                       <Input
                         value={warpPlus}
                         value={warpPlus}
-                        placeholder="26-char WARP+ key"
+                        placeholder={t('pages.xray.warp.keyPlaceholder')}
                         onChange={(e) => {
                         onChange={(e) => {
                           setWarpPlus(e.target.value);
                           setWarpPlus(e.target.value);
                           setLicenseError('');
                           setLicenseError('');
@@ -268,7 +270,7 @@ export default function WarpModal({
                           loading={loading}
                           loading={loading}
                           onClick={updateLicense}
                           onClick={updateLicense}
                         >
                         >
-                          Update
+                          {t('update')}
                         </Button>
                         </Button>
                         {licenseError && (
                         {licenseError && (
                           <Alert title={licenseError} type="error" showIcon className="license-error" />
                           <Alert title={licenseError} type="error" showIcon className="license-error" />
@@ -281,9 +283,9 @@ export default function WarpModal({
             ]}
             ]}
           />
           />
 
 
-          <Divider className="zero-margin">Account info</Divider>
+          <Divider className="zero-margin">{t('pages.xray.warp.accountInfo')}</Divider>
           <Button className="my-8" loading={loading} type="primary" icon={<SyncOutlined />} onClick={getConfig}>
           <Button className="my-8" loading={loading} type="primary" icon={<SyncOutlined />} onClick={getConfig}>
-            Refresh
+            {t('refresh')}
           </Button>
           </Button>
 
 
           {hasConfig && (
           {hasConfig && (
@@ -291,38 +293,38 @@ export default function WarpModal({
               <table className="warp-data-table">
               <table className="warp-data-table">
                 <tbody>
                 <tbody>
                   <tr className="row-odd">
                   <tr className="row-odd">
-                    <td>Device name</td>
+                    <td>{t('pages.xray.warp.deviceName')}</td>
                     <td>{warpConfig?.name}</td>
                     <td>{warpConfig?.name}</td>
                   </tr>
                   </tr>
                   <tr>
                   <tr>
-                    <td>Device model</td>
+                    <td>{t('pages.xray.warp.deviceModel')}</td>
                     <td>{warpConfig?.model}</td>
                     <td>{warpConfig?.model}</td>
                   </tr>
                   </tr>
                   <tr className="row-odd">
                   <tr className="row-odd">
-                    <td>Device enabled</td>
+                    <td>{t('pages.xray.warp.deviceEnabled')}</td>
                     <td>{String(warpConfig?.enabled)}</td>
                     <td>{String(warpConfig?.enabled)}</td>
                   </tr>
                   </tr>
                   {warpConfig?.account && (
                   {warpConfig?.account && (
                     <>
                     <>
                       <tr>
                       <tr>
-                        <td>Account type</td>
+                        <td>{t('pages.xray.warp.accountType')}</td>
                         <td>{warpConfig.account.account_type}</td>
                         <td>{warpConfig.account.account_type}</td>
                       </tr>
                       </tr>
                       <tr className="row-odd">
                       <tr className="row-odd">
-                        <td>Role</td>
+                        <td>{t('pages.xray.warp.role')}</td>
                         <td>{warpConfig.account.role}</td>
                         <td>{warpConfig.account.role}</td>
                       </tr>
                       </tr>
                       <tr>
                       <tr>
-                        <td>WARP+ data</td>
+                        <td>{t('pages.xray.warp.warpPlusData')}</td>
                         <td>{SizeFormatter.sizeFormat(warpConfig.account.premium_data)}</td>
                         <td>{SizeFormatter.sizeFormat(warpConfig.account.premium_data)}</td>
                       </tr>
                       </tr>
                       <tr className="row-odd">
                       <tr className="row-odd">
-                        <td>Quota</td>
+                        <td>{t('pages.xray.warp.quota')}</td>
                         <td>{SizeFormatter.sizeFormat(warpConfig.account.quota)}</td>
                         <td>{SizeFormatter.sizeFormat(warpConfig.account.quota)}</td>
                       </tr>
                       </tr>
                       {warpConfig.account.usage != null && (
                       {warpConfig.account.usage != null && (
                         <tr>
                         <tr>
-                          <td>Usage</td>
+                          <td>{t('pages.xray.warp.usage')}</td>
                           <td>{SizeFormatter.sizeFormat(warpConfig.account.usage)}</td>
                           <td>{SizeFormatter.sizeFormat(warpConfig.account.usage)}</td>
                         </tr>
                         </tr>
                       )}
                       )}
@@ -331,19 +333,19 @@ export default function WarpModal({
                 </tbody>
                 </tbody>
               </table>
               </table>
 
 
-              <Divider className="my-10">Outbound status</Divider>
+              <Divider className="my-10">{t('pages.xray.outbound.outboundStatus')}</Divider>
               {warpOutboundIndex >= 0 ? (
               {warpOutboundIndex >= 0 ? (
                 <>
                 <>
-                  <Tag color="green">Enabled</Tag>
+                  <Tag color="green">{t('enabled')}</Tag>
                   <Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
                   <Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
-                    Reset
+                    {t('reset')}
                   </Button>
                   </Button>
                 </>
                 </>
               ) : (
               ) : (
                 <>
                 <>
-                  <Tag color="orange">Disabled</Tag>
+                  <Tag color="orange">{t('disabled')}</Tag>
                   <Button type="primary" loading={loading} className="ml-8" icon={<PlusOutlined />} onClick={addOutbound}>
                   <Button type="primary" loading={loading} className="ml-8" icon={<PlusOutlined />} onClick={addOutbound}>
-                    Add outbound
+                    {t('pages.xray.warp.addOutbound')}
                   </Button>
                   </Button>
                 </>
                 </>
               )}
               )}

+ 6 - 6
frontend/src/pages/xray/XrayPage.tsx

@@ -223,10 +223,10 @@ export default function XrayPage() {
 
 
   function confirmRestart() {
   function confirmRestart() {
     modal.confirm({
     modal.confirm({
-      title: 'Restart xray?',
-      content: 'Reloads the xray service with the saved configuration.',
-      okText: 'Restart',
-      cancelText: 'Cancel',
+      title: t('pages.xray.restartConfirmTitle'),
+      content: t('pages.xray.restartConfirmContent'),
+      okText: t('pages.xray.restart'),
+      cancelText: t('cancel'),
       onOk: () => restartXray(),
       onOk: () => restartXray(),
     });
     });
   }
   }
@@ -255,7 +255,7 @@ export default function XrayPage() {
 
 
         <Layout className="content-shell">
         <Layout className="content-shell">
           <Layout.Content id="content-layout" className="content-area">
           <Layout.Content id="content-layout" className="content-area">
-            <Spin spinning={spinning || !fetched} delay={200} description="Loading…" size="large">
+            <Spin spinning={spinning || !fetched} delay={200} description={t('loading')} size="large">
               {!fetched ? (
               {!fetched ? (
                 <div className="loading-spacer" />
                 <div className="loading-spacer" />
               ) : fetchError ? (
               ) : fetchError ? (
@@ -281,7 +281,7 @@ export default function XrayPage() {
                             {restartResult && (
                             {restartResult && (
                               <Popover
                               <Popover
                                 placement="rightTop"
                                 placement="rightTop"
-                                title="Xray restart output"
+                                title={t('pages.xray.restartOutputTitle')}
                                 content={<pre className="restart-result">{restartResult}</pre>}
                                 content={<pre className="restart-result">{restartResult}</pre>}
                               >
                               >
                                 <QuestionCircleOutlined className="restart-icon" />
                                 <QuestionCircleOutlined className="restart-icon" />

+ 21 - 9
web/service/client.go

@@ -808,6 +808,12 @@ func (s *ClientService) BulkAttach(inboundSvc *InboundService, emails []string,
 		return result, false, nil
 		return result, false, nil
 	}
 	}
 
 
+	recordErr := func(format string, args ...any) {
+		msg := fmt.Sprintf(format, args...)
+		result.Errors = append(result.Errors, msg)
+		logger.Warningf("[BulkAttach] %s", msg)
+	}
+
 	records := make([]*model.ClientRecord, 0, len(emails))
 	records := make([]*model.ClientRecord, 0, len(emails))
 	seenEmail := make(map[string]struct{}, len(emails))
 	seenEmail := make(map[string]struct{}, len(emails))
 	for _, email := range emails {
 	for _, email := range emails {
@@ -821,7 +827,7 @@ func (s *ClientService) BulkAttach(inboundSvc *InboundService, emails []string,
 		seenEmail[key] = struct{}{}
 		seenEmail[key] = struct{}{}
 		rec, err := s.GetRecordByEmail(nil, email)
 		rec, err := s.GetRecordByEmail(nil, email)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("%s: %v", email, err))
+			recordErr("%s: %v", email, err)
 			continue
 			continue
 		}
 		}
 		records = append(records, rec)
 		records = append(records, rec)
@@ -831,12 +837,12 @@ func (s *ClientService) BulkAttach(inboundSvc *InboundService, emails []string,
 	for _, ibId := range inboundIds {
 	for _, ibId := range inboundIds {
 		inbound, err := inboundSvc.GetInbound(ibId)
 		inbound, err := inboundSvc.GetInbound(ibId)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("inbound %d: %v", ibId, err))
+			recordErr("inbound %d: %v", ibId, err)
 			continue
 			continue
 		}
 		}
 		existingClients, err := inboundSvc.GetClients(inbound)
 		existingClients, err := inboundSvc.GetClients(inbound)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("inbound %d: %v", ibId, err))
+			recordErr("inbound %d: %v", ibId, err)
 			continue
 			continue
 		}
 		}
 		have := make(map[string]struct{}, len(existingClients))
 		have := make(map[string]struct{}, len(existingClients))
@@ -853,7 +859,7 @@ func (s *ClientService) BulkAttach(inboundSvc *InboundService, emails []string,
 			client := *rec.ToClient()
 			client := *rec.ToClient()
 			client.UpdatedAt = time.Now().UnixMilli()
 			client.UpdatedAt = time.Now().UnixMilli()
 			if err := s.fillProtocolDefaults(&client, inbound); err != nil {
 			if err := s.fillProtocolDefaults(&client, inbound); err != nil {
-				result.Errors = append(result.Errors, fmt.Sprintf("%s -> inbound %d: %v", rec.Email, ibId, err))
+				recordErr("%s -> inbound %d: %v", rec.Email, ibId, err)
 				continue
 				continue
 			}
 			}
 			clientsToAdd = append(clientsToAdd, client)
 			clientsToAdd = append(clientsToAdd, client)
@@ -865,12 +871,12 @@ func (s *ClientService) BulkAttach(inboundSvc *InboundService, emails []string,
 
 
 		payload, err := json.Marshal(map[string][]model.Client{"clients": clientsToAdd})
 		payload, err := json.Marshal(map[string][]model.Client{"clients": clientsToAdd})
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("inbound %d: %v", ibId, err))
+			recordErr("inbound %d: %v", ibId, err)
 			continue
 			continue
 		}
 		}
 		nr, err := s.AddInboundClient(inboundSvc, &model.Inbound{Id: ibId, Settings: string(payload)})
 		nr, err := s.AddInboundClient(inboundSvc, &model.Inbound{Id: ibId, Settings: string(payload)})
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("inbound %d: %v", ibId, err))
+			recordErr("inbound %d: %v", ibId, err)
 			continue
 			continue
 		}
 		}
 		if nr {
 		if nr {
@@ -902,6 +908,12 @@ func (s *ClientService) BulkDetach(inboundSvc *InboundService, emails []string,
 		return result, false, nil
 		return result, false, nil
 	}
 	}
 
 
+	recordErr := func(format string, args ...any) {
+		msg := fmt.Sprintf(format, args...)
+		result.Errors = append(result.Errors, msg)
+		logger.Warningf("[BulkDetach] %s", msg)
+	}
+
 	requested := make(map[int]struct{}, len(inboundIds))
 	requested := make(map[int]struct{}, len(inboundIds))
 	for _, id := range inboundIds {
 	for _, id := range inboundIds {
 		requested[id] = struct{}{}
 		requested[id] = struct{}{}
@@ -921,12 +933,12 @@ func (s *ClientService) BulkDetach(inboundSvc *InboundService, emails []string,
 
 
 		rec, err := s.GetRecordByEmail(nil, email)
 		rec, err := s.GetRecordByEmail(nil, email)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("%s: %v", email, err))
+			recordErr("%s: %v", email, err)
 			continue
 			continue
 		}
 		}
 		currentIds, err := s.GetInboundIdsForRecord(rec.Id)
 		currentIds, err := s.GetInboundIdsForRecord(rec.Id)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("%s: %v", email, err))
+			recordErr("%s: %v", email, err)
 			continue
 			continue
 		}
 		}
 		intersection := make([]int, 0, len(currentIds))
 		intersection := make([]int, 0, len(currentIds))
@@ -941,7 +953,7 @@ func (s *ClientService) BulkDetach(inboundSvc *InboundService, emails []string,
 		}
 		}
 		nr, err := s.Detach(inboundSvc, rec.Id, intersection)
 		nr, err := s.Detach(inboundSvc, rec.Id, intersection)
 		if err != nil {
 		if err != nil {
-			result.Errors = append(result.Errors, fmt.Sprintf("%s: %v", rec.Email, err))
+			recordErr("%s: %v", rec.Email, err)
 			continue
 			continue
 		}
 		}
 		if nr {
 		if nr {

+ 496 - 79
web/translation/ar-EG.json

@@ -8,15 +8,22 @@
   "save": "حفظ",
   "save": "حفظ",
   "logout": "تسجيل خروج",
   "logout": "تسجيل خروج",
   "create": "إنشاء",
   "create": "إنشاء",
+  "add": "إضافة",
+  "remove": "إزالة",
   "update": "تحديث",
   "update": "تحديث",
   "copy": "نسخ",
   "copy": "نسخ",
   "copied": "اتنسخ",
   "copied": "اتنسخ",
+  "more": "المزيد",
   "download": "تحميل",
   "download": "تحميل",
   "remark": "ملاحظة",
   "remark": "ملاحظة",
   "enable": "مفعل",
   "enable": "مفعل",
   "protocol": "بروتوكول",
   "protocol": "بروتوكول",
   "search": "بحث",
   "search": "بحث",
-  "filter": "فلترة",
+  "filter": "تصفية",
+  "all": "الكل",
+  "from": "من",
+  "to": "إلى",
+  "done": "تم",
   "loading": "جاري التحميل...",
   "loading": "جاري التحميل...",
   "refresh": "تحديث",
   "refresh": "تحديث",
   "clear": "مسح",
   "clear": "مسح",
@@ -27,28 +34,28 @@
   "check": "شيك",
   "check": "شيك",
   "indefinite": "غير محدد",
   "indefinite": "غير محدد",
   "unlimited": "غير محدود",
   "unlimited": "غير محدود",
-  "none": "مفيش",
+  "none": "لا شيء",
   "qrCode": "كود QR",
   "qrCode": "كود QR",
   "info": "معلومات أكتر",
   "info": "معلومات أكتر",
-  "edit": "تعديل",
+  "edit": "تحرير",
   "delete": "مسح",
   "delete": "مسح",
-  "reset": "إعادة ضبط",
+  "reset": "إعادة تعيين",
   "noData": "لا توجد بيانات.",
   "noData": "لا توجد بيانات.",
   "copySuccess": "اتنسخ بنجاح",
   "copySuccess": "اتنسخ بنجاح",
   "sure": "متأكد؟",
   "sure": "متأكد؟",
   "encryption": "تشفير",
   "encryption": "تشفير",
   "useIPv4ForHost": "استخدم IPv4 للمضيف",
   "useIPv4ForHost": "استخدم IPv4 للمضيف",
   "transmission": "نقل",
   "transmission": "نقل",
-  "host": "المستضيف",
-  "path": "مسار",
+  "host": "المضيف",
+  "path": "المسار",
   "camouflage": "تمويه",
   "camouflage": "تمويه",
   "status": "الحالة",
   "status": "الحالة",
   "enabled": "مفعل",
   "enabled": "مفعل",
   "disabled": "معطل",
   "disabled": "معطل",
   "depleted": "خلص",
   "depleted": "خلص",
   "depletingSoon": "هينتهي قريب",
   "depletingSoon": "هينتهي قريب",
-  "offline": "أوفلاين",
-  "online": "أونلاين",
+  "offline": "غير متصل",
+  "online": "متصل",
   "domainName": "اسم الدومين",
   "domainName": "اسم الدومين",
   "monitor": "المسمع IP",
   "monitor": "المسمع IP",
   "certificate": "شهادة رقمية",
   "certificate": "شهادة رقمية",
@@ -95,10 +102,11 @@
     "dark": "داكن",
     "dark": "داكن",
     "ultraDark": "داكن جدًا",
     "ultraDark": "داكن جدًا",
     "dashboard": "نظرة عامة",
     "dashboard": "نظرة عامة",
-    "inbounds": "الإدخالات",
+    "inbounds": "الواردات",
     "clients": "العملاء",
     "clients": "العملاء",
+    "groups": "المجموعات",
     "nodes": "النودز",
     "nodes": "النودز",
-    "settings": "إعدادات البانل",
+    "settings": "إعدادات اللوحة",
     "xray": "إعدادات Xray",
     "xray": "إعدادات Xray",
     "apiDocs": "توثيق API",
     "apiDocs": "توثيق API",
     "logout": "تسجيل خروج",
     "logout": "تسجيل خروج",
@@ -120,13 +128,13 @@
     },
     },
     "index": {
     "index": {
       "title": "نظرة عامة",
       "title": "نظرة عامة",
-      "cpu": "المعالج",
+      "cpu": "CPU",
       "logicalProcessors": "المعالجات المنطقية",
       "logicalProcessors": "المعالجات المنطقية",
       "frequency": "التردد",
       "frequency": "التردد",
       "swap": "Swap",
       "swap": "Swap",
       "storage": "تخزين",
       "storage": "تخزين",
-      "memory": "رام",
-      "threads": "خيوط المعالجة",
+      "memory": "RAM",
+      "threads": "خيوط",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
       "stopXray": "إيقاف",
       "stopXray": "إيقاف",
       "restartXray": "إعادة تشغيل",
       "restartXray": "إعادة تشغيل",
@@ -143,7 +151,7 @@
       "xrayStatusUnknown": "مش معروف",
       "xrayStatusUnknown": "مش معروف",
       "xrayStatusRunning": "شغالة",
       "xrayStatusRunning": "شغالة",
       "xrayStatusStop": "متوقفة",
       "xrayStatusStop": "متوقفة",
-      "xrayStatusError": "فيها غلطة",
+      "xrayStatusError": "خطأ",
       "xrayErrorPopoverTitle": "حصل خطأ أثناء تشغيل Xray",
       "xrayErrorPopoverTitle": "حصل خطأ أثناء تشغيل Xray",
       "operationHours": "مدة التشغيل",
       "operationHours": "مدة التشغيل",
       "systemHistoryTitle": "تاريخ النظام",
       "systemHistoryTitle": "تاريخ النظام",
@@ -186,14 +194,14 @@
       "customGeoTitle": "GeoSite / GeoIP مخصص",
       "customGeoTitle": "GeoSite / GeoIP مخصص",
       "customGeoAdd": "إضافة",
       "customGeoAdd": "إضافة",
       "customGeoType": "النوع",
       "customGeoType": "النوع",
-      "customGeoAlias": "الاسم المستعار",
+      "customGeoAlias": "اسم مستعار",
       "customGeoUrl": "URL",
       "customGeoUrl": "URL",
       "customGeoEnabled": "مفعّل",
       "customGeoEnabled": "مفعّل",
       "customGeoLastUpdated": "آخر تحديث",
       "customGeoLastUpdated": "آخر تحديث",
       "customGeoExtColumn": "التوجيه (ext:…)",
       "customGeoExtColumn": "التوجيه (ext:…)",
       "customGeoToastUpdateAll": "تم تحديث جميع المصادر المخصصة",
       "customGeoToastUpdateAll": "تم تحديث جميع المصادر المخصصة",
       "customGeoActions": "إجراءات",
       "customGeoActions": "إجراءات",
-      "customGeoEdit": "تعديل",
+      "customGeoEdit": "تحرير",
       "customGeoDelete": "حذف",
       "customGeoDelete": "حذف",
       "customGeoDownload": "تحديث الآن",
       "customGeoDownload": "تحديث الآن",
       "customGeoModalAdd": "إضافة geo مخصص",
       "customGeoModalAdd": "إضافة geo مخصص",
@@ -228,7 +236,7 @@
       "dontRefresh": "التثبيت شغال، متعملش Refresh للصفحة",
       "dontRefresh": "التثبيت شغال، متعملش Refresh للصفحة",
       "logs": "السجلات",
       "logs": "السجلات",
       "config": "الإعدادات",
       "config": "الإعدادات",
-      "backup": "نسخة احتياطية",
+      "backup": "نسخ احتياطي",
       "backupTitle": "نسخ احتياطي واستعادة",
       "backupTitle": "نسخ احتياطي واستعادة",
       "exportDatabase": "اخزن نسخة",
       "exportDatabase": "اخزن نسخة",
       "exportDatabaseDesc": "اضغط عشان تحمل ملف .db يحتوي على نسخة احتياطية لقاعدة البيانات الحالية على جهازك.",
       "exportDatabaseDesc": "اضغط عشان تحمل ملف .db يحتوي على نسخة احتياطية لقاعدة البيانات الحالية على جهازك.",
@@ -241,18 +249,18 @@
       "getConfigError": "حدث خطأ أثناء استرجاع ملف الإعدادات"
       "getConfigError": "حدث خطأ أثناء استرجاع ملف الإعدادات"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "الإدخالات",
+      "title": "الواردات",
       "totalDownUp": "إجمالي المرسل/المستقبل",
       "totalDownUp": "إجمالي المرسل/المستقبل",
       "totalUsage": "إجمالي الاستخدام",
       "totalUsage": "إجمالي الاستخدام",
       "inboundCount": "عدد الإدخالات",
       "inboundCount": "عدد الإدخالات",
       "operate": "القائمة",
       "operate": "القائمة",
       "enable": "مفعل",
       "enable": "مفعل",
       "remark": "ملاحظة",
       "remark": "ملاحظة",
-      "node": "نود",
+      "node": "العقدة",
       "deployTo": "نشر على",
       "deployTo": "نشر على",
       "localPanel": "بانل محلي",
       "localPanel": "بانل محلي",
       "fallbacks": {
       "fallbacks": {
-        "title": "الـ Fallbacks",
+        "title": "Fallbacks",
         "help": "عند وصول اتصال إلى هذا الـ inbound لا يطابق أي عميل، يتم توجيهه إلى inbound آخر. اختر فرعًا أدناه وسيتم ملء حقول التوجيه (SNI / ALPN / Path / xver) تلقائيًا من نقل الفرع — في الغالب لا تحتاج إلى أي تعديل إضافي. يجب أن يستمع كل فرع على 127.0.0.1 مع security=none.",
         "help": "عند وصول اتصال إلى هذا الـ inbound لا يطابق أي عميل، يتم توجيهه إلى inbound آخر. اختر فرعًا أدناه وسيتم ملء حقول التوجيه (SNI / ALPN / Path / xver) تلقائيًا من نقل الفرع — في الغالب لا تحتاج إلى أي تعديل إضافي. يجب أن يستمع كل فرع على 127.0.0.1 مع security=none.",
         "empty": "لا توجد fallbacks بعد",
         "empty": "لا توجد fallbacks بعد",
         "add": "إضافة fallback",
         "add": "إضافة fallback",
@@ -269,15 +277,15 @@
         "defaultCatchAll": "افتراضي — يلتقط أي شيء آخر"
         "defaultCatchAll": "افتراضي — يلتقط أي شيء آخر"
       },
       },
       "protocol": "بروتوكول",
       "protocol": "بروتوكول",
-      "port": "بورت",
-      "portMap": "خريطة البورت",
-      "traffic": "الترافيك",
+      "port": "المنفذ",
+      "portMap": "تعيين المنفذ",
+      "traffic": "حركة المرور",
       "details": "تفاصيل",
       "details": "تفاصيل",
-      "transportConfig": "نقل",
+      "transportConfig": "النقل",
       "expireDate": "المدة",
       "expireDate": "المدة",
       "createdAt": "تاريخ الإنشاء",
       "createdAt": "تاريخ الإنشاء",
       "updatedAt": "تاريخ التحديث",
       "updatedAt": "تاريخ التحديث",
-      "resetTraffic": "إعادة ضبط الترافيك",
+      "resetTraffic": "إعادة تعيين حركة المرور",
       "addInbound": "أضف إدخال",
       "addInbound": "أضف إدخال",
       "generalActions": "إجراءات عامة",
       "generalActions": "إجراءات عامة",
       "modifyInbound": "تعديل الإدخال",
       "modifyInbound": "تعديل الإدخال",
@@ -292,11 +300,29 @@
       "delAllClients": "حذف جميع العملاء",
       "delAllClients": "حذف جميع العملاء",
       "delAllClientsConfirmTitle": "حذف جميع العملاء البالغ عددهم {count} من \"{remark}\"؟",
       "delAllClientsConfirmTitle": "حذف جميع العملاء البالغ عددهم {count} من \"{remark}\"؟",
       "delAllClientsConfirmContent": "يزيل كل عميل من هذا الإدخال ويحذف سجلات حركة المرور الخاصة بهم. يتم الاحتفاظ بالإدخال نفسه. لا يمكن التراجع عن هذا.",
       "delAllClientsConfirmContent": "يزيل كل عميل من هذا الإدخال ويحذف سجلات حركة المرور الخاصة بهم. يتم الاحتفاظ بالإدخال نفسه. لا يمكن التراجع عن هذا.",
+      "attachClients": "إرفاق عملاء بـ…",
+      "addClientsToGroup": "إضافة عملاء إلى مجموعة…",
+      "attachClientsTitle": "إرفاق عملاء من «{remark}»",
+      "attachClientsDesc": "يربط نفس {count} عميل (UUID/كلمة المرور وحركة المرور المشتركة) بالواردات المحددة. يبقون في هذا الوارد أيضاً.",
+      "attachClientsTargets": "الواردات الهدف",
+      "attachClientsNoTargets": "لا توجد واردات متوافقة أخرى للإرفاق.",
+      "attachClientsResult": "أُرفق {attached}، تم تخطي {skipped}.",
+      "attachClientsResultMixed": "أُرفق {attached}، تخطي {skipped}، أخطاء {errors}.",
+      "attachClientsSelectLabel": "العملاء للإرفاق",
+      "attachClientsSearchPlaceholder": "ابحث بالبريد أو التعليق",
+      "attachClientsStatusDisabled": "معطل",
+      "attachClientsSelectedCount": "{selected} من {total} محدد",
+      "detachClients": "فصل العملاء",
+      "detachClientsTitle": "فصل عملاء من «{remark}»",
+      "detachClientsDesc": "يزيل العميل (العملاء) المحدد من هذا الوارد فقط. تُحفظ سجلات العملاء (استخدم Delete للإزالة الكاملة). المصدر يحتوي على {count} عميل إجمالاً.",
+      "detachClientsResult": "فُصل {detached}، تم تخطي {skipped}.",
+      "detachClientsResultMixed": "فُصل {detached}، تخطي {skipped}، أخطاء {errors}.",
+      "detachClientsSelectLabel": "العملاء للفصل",
       "exportLinksTitle": "تصدير روابط الإدخال",
       "exportLinksTitle": "تصدير روابط الإدخال",
       "exportSubsTitle": "تصدير روابط الاشتراك",
       "exportSubsTitle": "تصدير روابط الاشتراك",
       "exportAllLinksTitle": "تصدير كل روابط الإدخالات",
       "exportAllLinksTitle": "تصدير كل روابط الإدخالات",
       "exportAllSubsTitle": "تصدير كل روابط الاشتراكات",
       "exportAllSubsTitle": "تصدير كل روابط الاشتراكات",
-      "inboundJsonTitle": "JSON الإدخال",
+      "inboundJsonTitle": "JSON الوارد",
       "deleteClient": "حذف العميل",
       "deleteClient": "حذف العميل",
       "deleteClientContent": "متأكد إنك عايز تحذف العميل؟",
       "deleteClientContent": "متأكد إنك عايز تحذف العميل؟",
       "resetTrafficContent": "متأكد إنك عايز تعيد ضبط الترافيك؟",
       "resetTrafficContent": "متأكد إنك عايز تعيد ضبط الترافيك؟",
@@ -306,7 +332,7 @@
       "destinationPort": "بورت الوجهة",
       "destinationPort": "بورت الوجهة",
       "targetAddress": "عنوان الهدف",
       "targetAddress": "عنوان الهدف",
       "monitorDesc": "سيبها فاضية لو عايز تستمع على كل الـ IPs",
       "monitorDesc": "سيبها فاضية لو عايز تستمع على كل الـ IPs",
-      "meansNoLimit": "= غير محدود. (الوحدة: جيجابايت)",
+      "meansNoLimit": "= غير محدود. (الوحدة: GB)",
       "totalFlow": "إجمالي التدفق",
       "totalFlow": "إجمالي التدفق",
       "leaveBlankToNeverExpire": "سيبها فاضية عشان ماتنتهيش",
       "leaveBlankToNeverExpire": "سيبها فاضية عشان ماتنتهيش",
       "noRecommendKeepDefault": "ننصح باستخدام الافتراضي",
       "noRecommendKeepDefault": "ننصح باستخدام الافتراضي",
@@ -333,7 +359,7 @@
       "delDepletedClients": "حذف العملاء اللي خلصت",
       "delDepletedClients": "حذف العملاء اللي خلصت",
       "delDepletedClientsTitle": "حذف العملاء اللي خلصت",
       "delDepletedClientsTitle": "حذف العملاء اللي خلصت",
       "delDepletedClientsContent": "متأكد إنك عايز تحذف كل العملاء اللي خلصت؟",
       "delDepletedClientsContent": "متأكد إنك عايز تحذف كل العملاء اللي خلصت؟",
-      "email": "الإيميل",
+      "email": "البريد",
       "emailDesc": "ادخل إيميل فريد.",
       "emailDesc": "ادخل إيميل فريد.",
       "IPLimit": "تحديد IP",
       "IPLimit": "تحديد IP",
       "IPLimitDesc": "بيعطل الإدخال لو العدد زاد عن القيمة المحددة. (0 = تعطيل)",
       "IPLimitDesc": "بيعطل الإدخال لو العدد زاد عن القيمة المحددة. (0 = تعطيل)",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "سجل تاريخ الـ IPs. (عشان تفعل الإدخال بعد التعطيل، امسح السجل)",
       "IPLimitlogDesc": "سجل تاريخ الـ IPs. (عشان تفعل الإدخال بعد التعطيل، امسح السجل)",
       "IPLimitlogclear": "امسح السجل",
       "IPLimitlogclear": "امسح السجل",
       "setDefaultCert": "استخدم شهادة البانل",
       "setDefaultCert": "استخدم شهادة البانل",
-      "streamTab": "الدفق",
+      "setDefaultCertEmpty": "لا توجد شهادة معدّة للوحة. عينّ واحدة من الإعدادات أولاً.",
+      "streamTab": "Stream",
       "securityTab": "الأمان",
       "securityTab": "الأمان",
-      "sniffingTab": "الاستشعار",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "البيانات الوصفية فقط",
       "sniffingMetadataOnly": "البيانات الوصفية فقط",
       "sniffingRouteOnly": "التوجيه فقط",
       "sniffingRouteOnly": "التوجيه فقط",
       "sniffingIpsExcluded": "IP المستثناة",
       "sniffingIpsExcluded": "IP المستثناة",
@@ -361,15 +388,14 @@
         "allHelp": "كائن الاتصال الوارد الكامل بكل الحقول في محرر واحد.",
         "allHelp": "كائن الاتصال الوارد الكامل بكل الحقول في محرر واحد.",
         "settings": "الإعدادات",
         "settings": "الإعدادات",
         "settingsHelp": "غلاف كتلة settings في Xray:",
         "settingsHelp": "غلاف كتلة settings في Xray:",
-        "sniffing": "الاستشعار",
+        "sniffing": "Sniffing",
         "sniffingHelp": "غلاف كتلة sniffing في Xray:",
         "sniffingHelp": "غلاف كتلة sniffing في Xray:",
-        "stream": "الدفق",
+        "stream": "Stream",
         "streamHelp": "غلاف كتلة stream في Xray:",
         "streamHelp": "غلاف كتلة stream في Xray:",
         "jsonErrorPrefix": "JSON متقدم"
         "jsonErrorPrefix": "JSON متقدم"
       },
       },
       "telegramDesc": "ادخل ID شات Telegram. (استخدم '/id' في البوت) أو ({'@'}userinfobot)",
       "telegramDesc": "ادخل ID شات Telegram. (استخدم '/id' في البوت) أو ({'@'}userinfobot)",
       "subscriptionDesc": "عشان تلاقي رابط الاشتراك، ادخل على 'التفاصيل'. وكمان ممكن تستخدم نفس الاسم لعدة عملاء.",
       "subscriptionDesc": "عشان تلاقي رابط الاشتراك، ادخل على 'التفاصيل'. وكمان ممكن تستخدم نفس الاسم لعدة عملاء.",
-      "info": "معلومات",
       "same": "نفسه",
       "same": "نفسه",
       "inboundData": "بيانات الإدخال",
       "inboundData": "بيانات الإدخال",
       "exportInbound": "تصدير الإدخال",
       "exportInbound": "تصدير الإدخال",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "حدث خطاء في الحصول على mldsa65.",
         "getNewmldsa65Error": "حدث خطاء في الحصول على mldsa65.",
         "getNewVlessEncError": "حدث خطأ أثناء الحصول على VlessEnc."
         "getNewVlessEncError": "حدث خطأ أثناء الحصول على VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "أعلى",
+        "moveDown": "أسفل",
+        "addAll": "إضافة الكل",
+        "addAllFallbackTooltip": "أضف صف fallback لكل وارد مؤهل لم يتم ربطه بعد",
+        "peers": "Peers",
+        "addPeer": "إضافة peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "ويندوز فقط. تُضاف CIDR تلقائياً إلى جدول التوجيه ليمر المرور المطابق عبر TUN.",
+        "autoOutboundsInterface": "واجهة صادر تلقائية",
+        "autoOutboundsInterfaceTooltip": "الواجهة الفعلية لحركة المرور الصادرة. استخدم 'auto' للاكتشاف؛ يتم تفعيلها تلقائياً عند تعيين Auto system routes.",
+        "rewriteAddress": "إعادة كتابة العنوان",
+        "rewritePort": "إعادة كتابة المنفذ",
+        "allowedNetwork": "الشبكة المسموح بها",
+        "followRedirect": "اتبع إعادة التوجيه",
+        "accounts": "الحسابات",
+        "allowTransparent": "السماح بالشفاف",
+        "encryptionMethod": "طريقة التشفير",
+        "visionTestseed": "Vision testseed",
+        "version": "الإصدار",
+        "udpIdleTimeout": "UDP idle timeout (ثانية)",
+        "masquerade": "Masquerade",
+        "type": "النوع",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "إعادة كتابة Host",
+        "skipTlsVerify": "تخطي التحقق من TLS",
+        "directory": "الدليل",
+        "statusCode": "رمز الحالة",
+        "body": "Body",
+        "headers": "الترويسات",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "إصدار الطلب",
+        "requestMethod": "طريقة الطلب",
+        "requestPath": "مسار الطلب",
+        "requestHeaders": "ترويسات الطلب",
+        "responseVersion": "إصدار الاستجابة",
+        "responseStatus": "حالة الاستجابة",
+        "responseReason": "سبب الاستجابة",
+        "responseHeaders": "ترويسات الاستجابة",
+        "heartbeatPeriod": "فترة Heartbeat",
+        "serviceName": "اسم الخدمة",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "الحد الأقصى للرفع المخزن",
+        "maxUploadSize": "حجم الرفع الأقصى (بايت)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "أقصى بايت ترويسة الخادم",
+        "paddingBytes": "بايتات Padding",
+        "uplinkHttpMethod": "Uplink HTTP method",
+        "paddingObfsMode": "وضع تشويش Padding",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "موضع Padding",
+        "paddingMethod": "طريقة Padding",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "بدون ترويسة SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "رفع (MB/s)",
+        "downlinkMbps": "تنزيل (MB/s)",
+        "cwndMultiplier": "معامل CWND",
+        "maxSendingWindow": "أقصى نافذة إرسال",
+        "externalProxy": "وكيل خارجي",
+        "sniPlaceholder": "SNI (افتراضياً host)",
+        "fingerprint": "بصمة",
+        "defaultOption": "افتراضي",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "V6 فقط",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For موثوق",
+        "addressPortStrategy": "استراتيجية العنوان+المنفذ",
+        "tryDelayMs": "تأخير المحاولة (ms)",
+        "prioritizeIPv6": "أولوية IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "أقصى محاولات متزامنة",
+        "customSockopt": "sockopt مخصص",
+        "addCustomOption": "إضافة خيار مخصص",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "تلقائي",
+        "minMaxVersion": "إصدار أدنى/أقصى",
+        "rejectUnknownSni": "رفض SNI غير معروف",
+        "disableSystemRoot": "تعطيل System Root",
+        "sessionResumption": "استئناف الجلسة",
+        "oneTimeLoading": "تحميل لمرة واحدة",
+        "usageOption": "خيار الاستخدام",
+        "buildChain": "بناء السلسلة",
+        "echKey": "ECH key",
+        "echConfig": "تكوين ECH",
+        "getNewEchCert": "احصل على شهادة ECH جديدة",
+        "show": "عرض",
+        "xver": "Xver",
+        "target": "الهدف",
+        "maxTimeDiff": "أقصى فرق زمن (ms)",
+        "minClientVer": "أدنى إصدار للعميل",
+        "maxClientVer": "أقصى إصدار للعميل",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "احصل على شهادة جديدة",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "احصل على Seed جديد"
+      },
+      "info": {
+        "mode": "الوضع",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "اسم الواجهة",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "واجهة الصادر",
+        "autoSystemRoutes": "توجيهات نظام تلقائية",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN بدون نواة",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "تكوين Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "طلب",
           "request": "طلب",
@@ -416,7 +575,7 @@
         "tcp": {
         "tcp": {
           "version": "نسخة",
           "version": "نسخة",
           "method": "طريقة",
           "method": "طريقة",
-          "path": "مسار",
+          "path": "المسار",
           "status": "الحالة",
           "status": "الحالة",
           "statusDescription": "وصف الحالة",
           "statusDescription": "وصف الحالة",
           "requestHeader": "رأس الطلب",
           "requestHeader": "رأس الطلب",
@@ -456,6 +615,20 @@
       "days": "يوم",
       "days": "يوم",
       "renew": "تجديد تلقائي",
       "renew": "تجديد تلقائي",
       "renewDesc": "تجديد تلقائي بعد انتهاء الصلاحية. (0 = تعطيل) (الوحدة: يوم)",
       "renewDesc": "تجديد تلقائي بعد انتهاء الصلاحية. (0 = تعطيل) (الوحدة: يوم)",
+      "searchPlaceholder": "ابحث بالبريد، التعليق، sub ID، UUID، كلمة المرور، auth…",
+      "filterTitle": "تصفية العملاء",
+      "clearAllFilters": "مسح الكل",
+      "sortOldest": "الأقدم أولاً",
+      "sortNewest": "الأحدث أولاً",
+      "sortRecentlyUpdated": "محدّث مؤخراً",
+      "sortRecentlyOnline": "متصل مؤخراً",
+      "sortEmailAZ": "بريد A→Z",
+      "sortEmailZA": "بريد Z→A",
+      "sortMostTraffic": "الأكثر استهلاكاً",
+      "sortHighestRemaining": "الأعلى متبقياً",
+      "sortExpiringSoonest": "الأقرب انتهاءً",
+      "has": "يملك",
+      "hasNot": "لا يملك",
       "title": "العملاء",
       "title": "العملاء",
       "actions": "الإجراءات",
       "actions": "الإجراءات",
       "totalGB": "مجموع المرسل/المستقبل (جيجابايت)",
       "totalGB": "مجموع المرسل/المستقبل (جيجابايت)",
@@ -465,7 +638,10 @@
       "password": "كلمة المرور",
       "password": "كلمة المرور",
       "subId": "معرّف الاشتراك",
       "subId": "معرّف الاشتراك",
       "online": "متصل",
       "online": "متصل",
-      "email": "البريد الإلكتروني",
+      "email": "البريد",
+      "group": "المجموعة",
+      "groupDesc": "تسمية منطقية لتجميع العملاء (مثل فريق، عميل، منطقة). يمكن تصفيتها من شريط الأدوات.",
+      "groupPlaceholder": "مثلاً customer-a",
       "comment": "ملاحظة",
       "comment": "ملاحظة",
       "traffic": "حركة المرور",
       "traffic": "حركة المرور",
       "offline": "غير متصل",
       "offline": "غير متصل",
@@ -483,17 +659,51 @@
       "selectInbound": "حدد اتصالاً واردًا واحدًا أو أكثر",
       "selectInbound": "حدد اتصالاً واردًا واحدًا أو أكثر",
       "noSubId": "هذا العميل ليس لديه subId، لا يوجد رابط قابل للمشاركة.",
       "noSubId": "هذا العميل ليس لديه subId، لا يوجد رابط قابل للمشاركة.",
       "noLinks": "لا توجد روابط للمشاركة — قم بإرفاق هذا العميل بأحد الاتصالات الواردة الداعمة للبروتوكول أولاً.",
       "noLinks": "لا توجد روابط للمشاركة — قم بإرفاق هذا العميل بأحد الاتصالات الواردة الداعمة للبروتوكول أولاً.",
-      "link": "رابط",
+      "link": "الرابط",
       "resetNotPossible": "قم بإرفاق هذا العميل بأحد الاتصالات الواردة أولاً.",
       "resetNotPossible": "قم بإرفاق هذا العميل بأحد الاتصالات الواردة أولاً.",
       "general": "عام",
       "general": "عام",
       "resetAllTraffics": "إعادة ضبط حركة مرور كل العملاء",
       "resetAllTraffics": "إعادة ضبط حركة مرور كل العملاء",
       "resetAllTrafficsTitle": "إعادة ضبط حركة مرور كل العملاء؟",
       "resetAllTrafficsTitle": "إعادة ضبط حركة مرور كل العملاء؟",
       "resetAllTrafficsContent": "يُعاد ضبط عدّاد الإرسال/الاستقبال لكل عميل إلى الصفر. لا تتأثر الحصص ومواعيد الانتهاء. لا يمكن التراجع.",
       "resetAllTrafficsContent": "يُعاد ضبط عدّاد الإرسال/الاستقبال لكل عميل إلى الصفر. لا تتأثر الحصص ومواعيد الانتهاء. لا يمكن التراجع.",
-      "empty": "لا يوجد عملاء بعد — أضف واحدًا للبدء.",
       "deleteConfirmTitle": "حذف العميل {email}؟",
       "deleteConfirmTitle": "حذف العميل {email}؟",
       "deleteConfirmContent": "سيؤدي هذا إلى إزالة العميل من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
       "deleteConfirmContent": "سيؤدي هذا إلى إزالة العميل من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
       "deleteSelected": "حذف ({count})",
       "deleteSelected": "حذف ({count})",
       "adjustSelected": "تعديل ({count})",
       "adjustSelected": "تعديل ({count})",
+      "subLinksSelected": "روابط الاشتراك ({count})",
+      "addToGroupTitle": "إضافة {count} عميل إلى مجموعة",
+      "addToGroupTooltip": "اختر مجموعة موجودة أو أدخل اسماً جديداً. استخدم Ungroup لإزالة العملاء من مجموعتهم الحالية.",
+      "addToGroupPlaceholder": "اسم المجموعة",
+      "addToGroupSuccessToast": "تمت إضافة {count} عميل إلى {group}",
+      "ungroupSuccessToast": "تم مسح المجموعة من {count} عميل",
+      "ungroup": "إزالة من المجموعة",
+      "ungroupConfirmTitle": "إزالة {count} عميل من مجموعتهم؟",
+      "ungroupConfirmContent": "يمسح تسمية المجموعة من كل عميل محدد. يُحفظ العملاء (استخدم Delete للإزالة الكاملة).",
+      "addToGroup": "إضافة إلى مجموعة",
+      "attach": "إرفاق",
+      "adjust": "ضبط",
+      "subLinks": "روابط الاشتراك",
+      "selectedCount": "{count} محدد",
+      "attachSelected": "إرفاق ({count})",
+      "attachToInboundsTitle": "إرفاق {count} عميل بالواردات",
+      "attachToInboundsDesc": "يربط {count} عميل المحدد (نفس UUID/كلمة المرور والمرور المشترك) بالواردات المختارة. يحتفظون بارتباطاتهم الحالية.",
+      "attachToInboundsTargets": "الواردات الهدف",
+      "attachToInboundsNoTargets": "لا توجد واردات متعددة المستخدمين للارتباط.",
+      "detachSelected": "فصل ({count})",
+      "detach": "فصل",
+      "detachFromInboundsTitle": "فصل {count} عميل من الواردات",
+      "detachFromInboundsDesc": "يزيل {count} عميل المحدد من الواردات المختارة. الأزواج التي لم يكن العميل مرتبطاً بها يتم تخطيها بصمت. تُحفظ سجلات العملاء (استخدم Delete للإزالة الكاملة).",
+      "detachFromInboundsTargets": "الواردات للفصل",
+      "detachFromInboundsNoTargets": "لا توجد واردات متعددة المستخدمين.",
+      "detachFromInboundsResult": "فُصل {detached}، تم تخطي {skipped}.",
+      "detachFromInboundsResultMixed": "فُصل {detached}، تخطي {skipped}، أخطاء {errors}.",
+      "subLinksTitle": "روابط الاشتراك ({count})",
+      "subLinkColumn": "رابط الاشتراك",
+      "subJsonLinkColumn": "رابط JSON للاشتراك",
+      "subLinksCopyAll": "نسخ الكل",
+      "subLinksCopiedAll": "تم نسخ {count} رابط",
+      "subLinksEmpty": "لا يحتوي أي من العملاء المحددين على معرف اشتراك.",
+      "subLinksDisabled": "خدمة الاشتراك معطلة.",
+      "subLinksDisabledHint": "فعّل الاشتراك من إعدادات اللوحة → الاشتراك لإنشاء الروابط.",
       "bulkDeleteConfirmTitle": "حذف {count} عميل؟",
       "bulkDeleteConfirmTitle": "حذف {count} عميل؟",
       "bulkDeleteConfirmContent": "سيتم إزالة كل عميل محدد من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
       "bulkDeleteConfirmContent": "سيتم إزالة كل عميل محدد من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
       "bulkAdjustTitle": "تعديل {count} عميل",
       "bulkAdjustTitle": "تعديل {count} عميل",
@@ -505,10 +715,11 @@
       "delDepletedConfirmTitle": "حذف العملاء المنتهية حصصهم؟",
       "delDepletedConfirmTitle": "حذف العملاء المنتهية حصصهم؟",
       "delDepletedConfirmContent": "يُحذف كل عميل استُنفِدت حصة حركة مروره أو انتهت صلاحيته. لا يمكن التراجع.",
       "delDepletedConfirmContent": "يُحذف كل عميل استُنفِدت حصة حركة مروره أو انتهت صلاحيته. لا يمكن التراجع.",
       "auth": "Auth",
       "auth": "Auth",
-      "hysteriaAuth": "Auth (Hysteria)",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "أمان VMess",
+      "reverseTag": "وسم عكسي",
       "reverseTagPlaceholder": "Reverse tag اختياري",
       "reverseTagPlaceholder": "Reverse tag اختياري",
       "telegramId": "معرّف مستخدم تلغرام",
       "telegramId": "معرّف مستخدم تلغرام",
       "telegramIdPlaceholder": "معرّف مستخدم تلغرام رقمي (0 = لا شيء)",
       "telegramIdPlaceholder": "معرّف مستخدم تلغرام رقمي (0 = لا شيء)",
@@ -528,13 +739,51 @@
         "delDepleted": "تم حذف {count} عميل منتهٍ"
         "delDepleted": "تم حذف {count} عميل منتهٍ"
       }
       }
     },
     },
+    "groups": {
+      "title": "المجموعات",
+      "name": "الاسم",
+      "clientCount": "عملاء في المجموعة",
+      "totalGroups": "إجمالي المجموعات",
+      "totalGroupedClients": "العملاء بمجموعة",
+      "emptyGroups": "مجموعات فارغة",
+      "addGroup": "إضافة مجموعة",
+      "createSuccess": "تم إنشاء المجموعة «{name}».",
+      "rename": "إعادة تسمية",
+      "renameTitle": "إعادة تسمية {name}",
+      "renameCollision": "مجموعة باسم «{name}» موجودة بالفعل.",
+      "renameSuccess": "تمت إعادة تسمية المجموعة على {count} عميل.",
+      "deleteConfirmTitle": "حذف المجموعة {name}؟",
+      "deleteConfirmContent": "يحذف المجموعة ويمسح تسميتها من {count} عميل. العملاء أنفسهم لا يُحذفون.",
+      "deleteSuccess": "تم مسح المجموعة من {count} عميل.",
+      "resetTraffic": "إعادة تعيين حركة المرور",
+      "resetConfirmTitle": "إعادة تعيين حركة المرور للمجموعة {name}؟",
+      "resetConfirmContent": "يصفر up/down لجميع {count} عميل في هذه المجموعة.",
+      "resetSuccess": "تمت إعادة تعيين حركة المرور لـ {count} عميل.",
+      "adjustSuccess": "تم ضبط {count} عميل في {name}.",
+      "emptyForAction": "هذه المجموعة فارغة.",
+      "deleteGroupOnly": "حذف المجموعة (مع الاحتفاظ بالعملاء)",
+      "deleteClients": "حذف عملاء المجموعة",
+      "deleteClientsConfirmTitle": "حذف جميع العملاء في {name}؟",
+      "deleteClientsConfirmContent": "يحذف {count} عميل نهائياً مع سجلات حركة المرور. تُمسح تسمية المجموعة أيضاً. لا يمكن التراجع.",
+      "deleteClientsSuccess": "تم حذف {count} عميل.",
+      "deleteClientsMixed": "{ok} حُذف، {failed} تم تخطيه",
+      "addToGroup": "إضافة عملاء…",
+      "addToGroupTitle": "إضافة عملاء إلى المجموعة «{name}»",
+      "addToGroupDesc": "اختر العملاء لإضافتهم إلى هذه المجموعة. يحتفظون بارتباطات الواردات الحالية؛ تتغير تسمية المجموعة فقط. لا تُعرض العملاء الذين هم في هذه المجموعة بالفعل.",
+      "addToGroupEmpty": "لا يوجد عملاء آخرون للإضافة.",
+      "addToGroupResult": "تمت إضافة {count} عميل إلى {name}.",
+      "removeFromGroup": "إزالة عملاء…",
+      "removeFromGroupTitle": "إزالة عملاء من المجموعة «{name}»",
+      "removeFromGroupDesc": "اختر الأعضاء لإزالتهم من هذه المجموعة. يُحفظ العملاء (استخدم «حذف عملاء المجموعة» للإزالة الكاملة).",
+      "removeFromGroupResult": "تمت إزالة {count} عميل من {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "النودز",
       "title": "النودز",
       "addNode": "إضافة نود",
       "addNode": "إضافة نود",
-      "editNode": "تعديل نود",
+      "editNode": "تحرير العقدة",
       "totalNodes": "إجمالي النودز",
       "totalNodes": "إجمالي النودز",
-      "onlineNodes": "أونلاين",
-      "offlineNodes": "أوفلاين",
+      "onlineNodes": "متصل",
+      "offlineNodes": "غير متصل",
       "avgLatency": "متوسط الكمون",
       "avgLatency": "متوسط الكمون",
       "name": "الاسم",
       "name": "الاسم",
       "namePlaceholder": "مثال: de-frankfurt-1",
       "namePlaceholder": "مثال: de-frankfurt-1",
@@ -542,9 +791,9 @@
       "remark": "ملاحظة",
       "remark": "ملاحظة",
       "scheme": "البروتوكول",
       "scheme": "البروتوكول",
       "address": "العنوان",
       "address": "العنوان",
-      "port": "البورت",
+      "port": "المنفذ",
       "basePath": "المسار الأساسي",
       "basePath": "المسار الأساسي",
-      "apiToken": "توكن API",
+      "apiToken": "رمز API",
       "apiTokenPlaceholder": "التوكن من صفحة إعدادات البانل البعيد",
       "apiTokenPlaceholder": "التوكن من صفحة إعدادات البانل البعيد",
       "apiTokenHint": "البانل البعيد بيعرض توكن API بتاعه في الإعدادات → توكن API.",
       "apiTokenHint": "البانل البعيد بيعرض توكن API بتاعه في الإعدادات → توكن API.",
       "regenerate": "تجديد التوكن",
       "regenerate": "تجديد التوكن",
@@ -553,7 +802,7 @@
       "allowPrivateAddressHint": "التفعيل فقط للعقد على شبكة خاصة أو VPN.",
       "allowPrivateAddressHint": "التفعيل فقط للعقد على شبكة خاصة أو VPN.",
       "enable": "مفعل",
       "enable": "مفعل",
       "status": "الحالة",
       "status": "الحالة",
-      "cpu": "المعالج",
+      "cpu": "CPU",
       "mem": "الذاكرة",
       "mem": "الذاكرة",
       "uptime": "مدة التشغيل",
       "uptime": "مدة التشغيل",
       "latency": "الكمون",
       "latency": "الكمون",
@@ -570,8 +819,8 @@
       "deleteConfirmTitle": "تحذف النود \"{name}\"؟",
       "deleteConfirmTitle": "تحذف النود \"{name}\"؟",
       "deleteConfirmContent": "ده هيوقّف مراقبة النود. البانل البعيد نفسه مش هيتأثر.",
       "deleteConfirmContent": "ده هيوقّف مراقبة النود. البانل البعيد نفسه مش هيتأثر.",
       "statusValues": {
       "statusValues": {
-        "online": "أونلاين",
-        "offline": "أوفلاين",
+        "online": "متصل",
+        "offline": "غير متصل",
         "unknown": "غير معروف"
         "unknown": "غير معروف"
       },
       },
       "toasts": {
       "toasts": {
@@ -590,7 +839,7 @@
       "title": "إعدادات البانل",
       "title": "إعدادات البانل",
       "save": "حفظ",
       "save": "حفظ",
       "infoDesc": "كل تغيير هتعمله هنا لازم يتخزن. ياريت تعيد تشغيل البانل عشان التعديلات تتفعل.",
       "infoDesc": "كل تغيير هتعمله هنا لازم يتخزن. ياريت تعيد تشغيل البانل عشان التعديلات تتفعل.",
-      "restartPanel": "إعادة تشغيل البانل",
+      "restartPanel": "إعادة تشغيل اللوحة",
       "restartPanelDesc": "متأكد إنك عايز تعيد تشغيل البانل؟ لو ماقدرتش تدخل بعد إعادة التشغيل، شوف سجل البانل على السيرفر.",
       "restartPanelDesc": "متأكد إنك عايز تعيد تشغيل البانل؟ لو ماقدرتش تدخل بعد إعادة التشغيل، شوف سجل البانل على السيرفر.",
       "restartPanelSuccess": "تم إعادة تشغيل اللوحة بنجاح",
       "restartPanelSuccess": "تم إعادة تشغيل اللوحة بنجاح",
       "actions": "إجراءات",
       "actions": "إجراءات",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "المسار الأساسي الافتراضي \"/\" معروف — غيّره إلى مسار عشوائي.",
       "warnDefaultBasePath": "المسار الأساسي الافتراضي \"/\" معروف — غيّره إلى مسار عشوائي.",
       "warnDefaultSubPath": "مسار الاشتراك الافتراضي \"/sub/\" معروف — قم بتغييره.",
       "warnDefaultSubPath": "مسار الاشتراك الافتراضي \"/sub/\" معروف — قم بتغييره.",
       "warnDefaultJsonPath": "مسار اشتراك JSON الافتراضي \"/json/\" معروف — قم بتغييره.",
       "warnDefaultJsonPath": "مسار اشتراك JSON الافتراضي \"/json/\" معروف — قم بتغييره.",
-      "TGBotSettings": "بوت Telegram",
+      "TGBotSettings": "بوت تيليجرام",
       "panelListeningIP": "IP الاستماع",
       "panelListeningIP": "IP الاستماع",
       "panelListeningIPDesc": "عنوان IP للبانل. (سيبه فاضي عشان يستمع على كل الـ IPs)",
       "panelListeningIPDesc": "عنوان IP للبانل. (سيبه فاضي عشان يستمع على كل الـ IPs)",
       "panelListeningDomain": "دومين الاستماع",
       "panelListeningDomain": "دومين الاستماع",
@@ -619,6 +868,8 @@
       "panelUrlPathDesc": "مسار URI للبانل. (يبدأ بـ '/' وبينتهي بـ '/')",
       "panelUrlPathDesc": "مسار URI للبانل. (يبدأ بـ '/' وبينتهي بـ '/')",
       "pageSize": "حجم الصفحة",
       "pageSize": "حجم الصفحة",
       "pageSizeDesc": "حدد حجم الصفحة لجدول الإدخالات. (0 = تعطيل)",
       "pageSizeDesc": "حدد حجم الصفحة لجدول الإدخالات. (0 = تعطيل)",
+      "panelProxy": "وكيل شبكة اللوحة",
+      "panelProxyDesc": "يوجه طلبات اللوحة الصادرة (تحديثات geo، فحص إصدارات Xray/اللوحة، تيليجرام) عبر هذا الوكيل لتجاوز فلترة GitHub/تيليجرام على الخادم. يقبل socks5:// أو http(s)://، مثل وارد SOCKS محلي لـ Xray. اتركه فارغاً للاتصال المباشر.",
       "remarkModel": "نموذج الملاحظة وحرف الفصل",
       "remarkModel": "نموذج الملاحظة وحرف الفصل",
       "datepicker": "نوع التقويم",
       "datepicker": "نوع التقويم",
       "datepickerPlaceholder": "اختار التاريخ",
       "datepickerPlaceholder": "اختار التاريخ",
@@ -630,11 +881,11 @@
       "newPassword": "الباسورد الجديد",
       "newPassword": "الباسورد الجديد",
       "telegramBotEnable": "تفعيل بوت Telegram",
       "telegramBotEnable": "تفعيل بوت Telegram",
       "telegramBotEnableDesc": "يفعل بوت Telegram.",
       "telegramBotEnableDesc": "يفعل بوت Telegram.",
-      "telegramToken": "توكن Telegram",
+      "telegramToken": "رمز تيليجرام",
       "telegramTokenDesc": "توكن البوت اللي جبت من '{'@'}BotFather'.",
       "telegramTokenDesc": "توكن البوت اللي جبت من '{'@'}BotFather'.",
-      "telegramProxy": "بروكسي SOCKS",
+      "telegramProxy": "وكيل SOCKS",
       "telegramProxyDesc": "يفعل بروكسي SOCKS5 للاتصال بـ Telegram. (اضبط الإعدادات حسب الدليل)",
       "telegramProxyDesc": "يفعل بروكسي SOCKS5 للاتصال بـ Telegram. (اضبط الإعدادات حسب الدليل)",
-      "telegramAPIServer": "سيرفر Telegram API",
+      "telegramAPIServer": "خادم API لتيليجرام",
       "telegramAPIServerDesc": "سيرفر Telegram API المستخدم. سيبه فاضي لاستخدام الافتراضي.",
       "telegramAPIServerDesc": "سيرفر Telegram API المستخدم. سيبه فاضي لاستخدام الافتراضي.",
       "telegramChatId": "ID شات الأدمن",
       "telegramChatId": "ID شات الأدمن",
       "telegramChatIdDesc": "ID شات الأدمن في Telegram. (مفصول بفواصل)(تقدر تجيبه من {'@'}userinfobot) أو (استخدم '/id' في البوت)",
       "telegramChatIdDesc": "ID شات الأدمن في Telegram. (مفصول بفواصل)(تقدر تجيبه من {'@'}userinfobot) أو (استخدم '/id' في البوت)",
@@ -658,6 +909,8 @@
       "subEnable": "تفعيل خدمة الاشتراك",
       "subEnable": "تفعيل خدمة الاشتراك",
       "subEnableDesc": "يفعل خدمة الاشتراك.",
       "subEnableDesc": "يفعل خدمة الاشتراك.",
       "subJsonEnable": "تمكين/تعطيل نقطة نهاية اشتراك JSON بشكل مستقل.",
       "subJsonEnable": "تمكين/تعطيل نقطة نهاية اشتراك JSON بشكل مستقل.",
+      "subJsonEnableTitle": "اشتراك JSON",
+      "subClashEnableTitle": "اشتراك Clash / Mihomo",
       "subTitle": "عنوان الاشتراك",
       "subTitle": "عنوان الاشتراك",
       "subTitleDesc": "العنوان اللي هيظهر في عميل VPN",
       "subTitleDesc": "العنوان اللي هيظهر في عميل VPN",
       "subSupportUrl": "رابط الدعم",
       "subSupportUrl": "رابط الدعم",
@@ -693,7 +946,7 @@
       "subURI": "مسار البروكسي العكسي",
       "subURI": "مسار البروكسي العكسي",
       "subURIDesc": "مسار URI لرابط الاشتراك عشان تستخدمه ورا البروكسي.",
       "subURIDesc": "مسار URI لرابط الاشتراك عشان تستخدمه ورا البروكسي.",
       "externalTrafficInformEnable": "تنبيه الترافيك الخارجي",
       "externalTrafficInformEnable": "تنبيه الترافيك الخارجي",
-      "externalTrafficInformEnableDesc": "يبعت تنبيه لـ API خارجي مع كل تحديث للترافيك.",
+      "externalTrafficInformEnableDesc": "إخطار واجهة API خارجية بكل تحديث لحركة المرور.",
       "externalTrafficInformURI": "مسار تنبيه الترافيك الخارجي",
       "externalTrafficInformURI": "مسار تنبيه الترافيك الخارجي",
       "externalTrafficInformURIDesc": "تحديثات الترافيك هتتبعت للمسار ده.",
       "externalTrafficInformURIDesc": "تحديثات الترافيك هتتبعت للمسار ده.",
       "restartXrayOnClientDisable": "إعادة تشغيل Xray بعد التعطيل التلقائي",
       "restartXrayOnClientDisable": "إعادة تشغيل Xray بعد التعطيل التلقائي",
@@ -703,7 +956,55 @@
       "fragmentSett": "إعدادات التجزئة",
       "fragmentSett": "إعدادات التجزئة",
       "noisesDesc": "يفعل التشويش.",
       "noisesDesc": "يفعل التشويش.",
       "noisesSett": "إعدادات التشويش",
       "noisesSett": "إعدادات التشويش",
-      "mux": "MUX",
+      "trustedProxyCidrs": "CIDR وكلاء موثوقين",
+      "trustedProxyCidrsDesc": "IPs/CIDRs مفصولة بفواصل يُسمح لها بتعيين ترويسات host، proto و client IP المعاد توجيهها.",
+      "ldap": {
+        "enable": "تفعيل مزامنة LDAP",
+        "host": "مضيف LDAP",
+        "port": "منفذ LDAP",
+        "useTls": "استخدام TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "مهيأة؛ اترك فارغاً للاحتفاظ بكلمة المرور الحالية.",
+        "passwordUnconfigured": "غير مهيأة.",
+        "passwordPlaceholder": "مهيأة — أدخل قيمة جديدة لاستبدالها",
+        "baseDn": "Base DN",
+        "userFilter": "مرشح المستخدم",
+        "userAttr": "خاصية المستخدم (username/email)",
+        "vlessField": "خاصية VLESS flag",
+        "flagField": "خاصية flag عامة (اختياري)",
+        "flagFieldDesc": "إذا تم تعيينها، تتجاوز VLESS flag — مثل shadowInactive.",
+        "truthyValues": "قيم Truthy",
+        "truthyValuesDesc": "مفصولة بفواصل؛ الافتراضي: true,1,yes,on",
+        "invertFlag": "عكس flag",
+        "invertFlagDesc": "فعّل عندما تعني الخاصية «معطل» (مثل shadowInactive).",
+        "syncSchedule": "جدول المزامنة",
+        "syncScheduleDesc": "سلسلة شبيهة بـ cron، مثل @every 1m",
+        "inboundTags": "وسوم الواردات",
+        "inboundTagsDesc": "الواردات التي يمكن لمزامنة LDAP إنشاء/حذف العملاء فيها تلقائياً.",
+        "noInbounds": "لم يتم العثور على واردات. أنشئ واحداً في الواردات أولاً.",
+        "autoCreate": "إنشاء عملاء تلقائياً",
+        "autoDelete": "حذف عملاء تلقائياً",
+        "defaultTotalGb": "الإجمالي الافتراضي (GB)",
+        "defaultExpiryDays": "الانتهاء الافتراضي (أيام)",
+        "defaultIpLimit": "حد IP الافتراضي"
+      },
+      "subFormats": {
+        "packets": "الحزم",
+        "length": "الطول",
+        "interval": "الفاصل",
+        "maxSplit": "أقصى تقسيم",
+        "noises": "الضوضاء",
+        "noiseItem": "ضوضاء №{n}",
+        "type": "النوع",
+        "packet": "حزمة",
+        "delayMs": "التأخير (ms)",
+        "applyTo": "تطبيق على",
+        "addNoise": "+ ضوضاء",
+        "concurrency": "التزامن",
+        "xudpConcurrency": "تزامن xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
+      "mux": "Mux",
       "muxDesc": "ينقل أكثر من تيار بيانات مستقل خلال تيار بيانات واحد قائم.",
       "muxDesc": "ينقل أكثر من تيار بيانات مستقل خلال تيار بيانات واحد قائم.",
       "muxSett": "إعدادات MUX",
       "muxSett": "إعدادات MUX",
       "direct": "اتصال مباشر",
       "direct": "اتصال مباشر",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "إعدادات Xray",
       "title": "إعدادات Xray",
       "save": "احفظ",
       "save": "احفظ",
-      "restart": "أعد تشغيل Xray",
+      "restart": "إعادة تشغيل Xray",
       "restartSuccess": "تم إعادة تشغيل Xray بنجاح",
       "restartSuccess": "تم إعادة تشغيل Xray بنجاح",
+      "restartOutputTitle": "مخرجات إعادة تشغيل Xray",
+      "restartConfirmTitle": "إعادة تشغيل xray؟",
+      "restartConfirmContent": "يعيد تحميل خدمة xray بالتكوين المحفوظ.",
       "stopSuccess": "تم إيقاف Xray بنجاح",
       "stopSuccess": "تم إيقاف Xray بنجاح",
       "restartError": "حدث خطأ أثناء إعادة تشغيل Xray.",
       "restartError": "حدث خطأ أثناء إعادة تشغيل Xray.",
       "stopError": "حدث خطأ أثناء إيقاف Xray.",
       "stopError": "حدث خطأ أثناء إيقاف Xray.",
@@ -765,7 +1069,7 @@
       "advancedTemplate": "متقدم",
       "advancedTemplate": "متقدم",
       "generalConfigs": "إعدادات عامة",
       "generalConfigs": "إعدادات عامة",
       "generalConfigsDesc": "الخيارات دي هتحدد التعديلات العامة.",
       "generalConfigsDesc": "الخيارات دي هتحدد التعديلات العامة.",
-      "logConfigs": "السجلات",
+      "logConfigs": "السجل",
       "logConfigsDesc": "السجلات ممكن تأثر على كفاءة السيرفر. ننصح بتفعيلها بحكمة لما تكون محتاجها.",
       "logConfigsDesc": "السجلات ممكن تأثر على كفاءة السيرفر. ننصح بتفعيلها بحكمة لما تكون محتاجها.",
       "blockConfigsDesc": "الخيارات دي هتحجب الترافيك بناءً على بروتوكولات ومواقع محددة.",
       "blockConfigsDesc": "الخيارات دي هتحجب الترافيك بناءً على بروتوكولات ومواقع محددة.",
       "basicRouting": "توجيه أساسي",
       "basicRouting": "توجيه أساسي",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "رابط اختبار المخرج",
       "outboundTestUrl": "رابط اختبار المخرج",
       "outboundTestUrlDesc": "الرابط المستخدم عند اختبار اتصال المخرج",
       "outboundTestUrlDesc": "الرابط المستخدم عند اختبار اتصال المخرج",
       "Torrent": "حظر بروتوكول التورنت",
       "Torrent": "حظر بروتوكول التورنت",
-      "Inbounds": "الإدخالات",
+      "Inbounds": "الواردات",
       "InboundsDesc": "قبول العملاء المعينين.",
       "InboundsDesc": "قبول العملاء المعينين.",
-      "Outbounds": "المخرجات",
+      "Outbounds": "الصادرات",
       "Balancers": "موازنات التحميل",
       "Balancers": "موازنات التحميل",
+      "balancerTagRequired": "الوسم مطلوب",
+      "balancerSelectorRequired": "اختر صادراً واحداً على الأقل",
       "OutboundsDesc": "حدد مسار الترافيك الصادر.",
       "OutboundsDesc": "حدد مسار الترافيك الصادر.",
       "Routings": "قواعد التوجيه",
       "Routings": "قواعد التوجيه",
       "RoutingsDesc": "أولوية كل قاعدة مهمة جداً!",
       "RoutingsDesc": "أولوية كل قاعدة مهمة جداً!",
@@ -832,6 +1138,73 @@
         "edit": "عدل القاعدة",
         "edit": "عدل القاعدة",
         "useComma": "عناصر مفصولة بفواصل"
         "useComma": "عناصر مفصولة بفواصل"
       },
       },
+      "routing": {
+        "dragToReorder": "اسحب لإعادة الترتيب"
+      },
+      "ruleForm": {
+        "sourceIps": "IPs المصدر",
+        "sourcePort": "منفذ المصدر",
+        "vlessRoute": "مسار VLESS",
+        "attributes": "الخصائص",
+        "value": "القيمة",
+        "user": "المستخدم",
+        "inboundTags": "وسوم الواردات",
+        "outboundTag": "وسم الصادر",
+        "balancerTag": "وسم الموازن",
+        "balancerTagTooltip": "يوجه حركة المرور عبر أحد موازنات الحمل المهيأة"
+      },
+      "outboundForm": {
+        "tagDuplicate": "الوسم مستخدم بالفعل من قبل صادر آخر",
+        "tagRequired": "الوسم مطلوب",
+        "tagPlaceholder": "وسم-فريد",
+        "localIpPlaceholder": "IP محلي",
+        "addressRequired": "العنوان مطلوب",
+        "portRequired": "المنفذ مطلوب",
+        "optional": "اختياري",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "إصدار UoT",
+        "inboundTag": "وسم الوارد",
+        "inboundTagPlaceholder": "وسم الوارد المستخدم في قواعد التوجيه",
+        "responseType": "نوع الاستجابة",
+        "rewriteNetwork": "إعادة كتابة الشبكة",
+        "unchanged": "(دون تغيير)",
+        "unchangedAddress": "(دون تغيير) مثل 1.1.1.1",
+        "rules": "القواعد",
+        "ruleN": "القاعدة {n}",
+        "action": "الإجراء",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "القواعد النهائية",
+        "overrideXrayPrivateIp": "تجاوز حظر IP الخاص الافتراضي في Xray",
+        "blockDelay": "تأخير الحظر (ms)",
+        "reverseSniffing": "Sniffing عكسي",
+        "workers": "Workers",
+        "reserved": "محجوز",
+        "minUploadInterval": "أدنى فاصل رفع (ms)",
+        "maxUploadSizeBytes": "حجم الرفع الأقصى (بايت)",
+        "uplinkChunkSize": "حجم chunk الرفع",
+        "noGrpcHeader": "بدون ترويسة gRPC",
+        "maxConcurrency": "أقصى تزامن",
+        "maxConnections": "أقصى اتصالات",
+        "maxReuseTimes": "أقصى مرات إعادة استخدام",
+        "maxRequestTimes": "أقصى طلبات",
+        "maxReusableSecs": "أقصى ثوانٍ قابلة لإعادة الاستخدام",
+        "keepAlivePeriod": "فترة keep alive",
+        "authPassword": "كلمة مرور Auth",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "اسم الخادم",
+        "verifyPeerName": "التحقق من اسم peer",
+        "pinnedSha256": "SHA256 مثبت",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "فاصل keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "الواجهة",
+        "ipv6Only": "IPv6 فقط",
+        "acceptProxyProtocol": "قبول proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (ثانية)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "أضف مخرج",
         "addOutbound": "أضف مخرج",
         "addReverse": "أضف عكسي",
         "addReverse": "أضف عكسي",
@@ -840,15 +1213,15 @@
         "reverseTag": "وسم العكسي",
         "reverseTag": "وسم العكسي",
         "reverseTagDesc": "وسم الخروج لبروكسي VLESS العكسي البسيط. اتركه فارغاً لتعطيله.",
         "reverseTagDesc": "وسم الخروج لبروكسي VLESS العكسي البسيط. اتركه فارغاً لتعطيله.",
         "reverseTagPlaceholder": "وسم الخروج (اتركه فارغاً للتعطيل)",
         "reverseTagPlaceholder": "وسم الخروج (اتركه فارغاً للتعطيل)",
-        "tag": "تاج",
+        "tag": "الوسم",
         "tagDesc": "تاج فريد",
         "tagDesc": "تاج فريد",
         "address": "العنوان",
         "address": "العنوان",
         "reverse": "عكسي",
         "reverse": "عكسي",
-        "domain": "دومين",
+        "domain": "النطاق",
         "type": "النوع",
         "type": "النوع",
-        "bridge": "جسر",
-        "portal": "بوابة",
-        "link": "رابط",
+        "bridge": "Bridge",
+        "portal": "Portal",
+        "link": "الرابط",
         "intercon": "تواصل",
         "intercon": "تواصل",
         "settings": "إعدادات",
         "settings": "إعدادات",
         "accountInfo": "معلومات الحساب",
         "accountInfo": "معلومات الحساب",
@@ -860,6 +1233,8 @@
         "testSuccess": "الاختبار ناجح",
         "testSuccess": "الاختبار ناجح",
         "testFailed": "فشل الاختبار",
         "testFailed": "فشل الاختبار",
         "testError": "فشل اختبار المخرج",
         "testError": "فشل اختبار المخرج",
+        "testModeTooltip": "TCP: فحص dial سريع. HTTP: طلب كامل عبر xray.",
+        "testAll": "اختبار الكل",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "رمز الوصول",
         "accessToken": "رمز الوصول",
         "country": "الدولة",
         "country": "الدولة",
@@ -874,8 +1249,18 @@
         "editBalancer": "عدل موازن التحميل",
         "editBalancer": "عدل موازن التحميل",
         "balancerStrategy": "استراتيجية الموازن",
         "balancerStrategy": "استراتيجية الموازن",
         "balancerSelectors": "المحددات",
         "balancerSelectors": "المحددات",
-        "tag": "تاج",
+        "tag": "الوسم",
         "tagDesc": "تاج فريد",
         "tagDesc": "تاج فريد",
+        "tagDuplicate": "الوسم مستخدم بالفعل من قبل موازن آخر",
+        "tagPlaceholder": "وسم موازن فريد",
+        "selector": "المحدد",
+        "fallback": "Fallback",
+        "expected": "المتوقع",
+        "expectedPlaceholder": "العدد الأمثل للعقد",
+        "maxRtt": "أقصى RTT",
+        "tolerance": "التحمل",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "ماينفعش تستخدم balancerTag و outboundTag مع بعض. لو اتستخدموا مع بعض، outboundTag هو اللي هيشتغل."
         "balancerDesc": "ماينفعش تستخدم balancerTag و outboundTag مع بعض. لو اتستخدموا مع بعض، outboundTag هو اللي هيشتغل."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "مستوى المستخدم",
         "userLevel": "مستوى المستخدم",
         "userLevelDesc": "ستستخدم جميع الاتصالات المُرسلة عبر هذا الإدخال مستوى المستخدم هذا. القيمة الافتراضية هي 0"
         "userLevelDesc": "ستستخدم جميع الاتصالات المُرسلة عبر هذا الإدخال مستوى المستخدم هذا. القيمة الافتراضية هي 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "المفتاح الخاص",
+        "noServers": "لم يتم العثور على خوادم للدولة المحددة",
+        "noPublicKey": "الخادم المحدد لا يُعلن عن مفتاح NordLynx العام.",
+        "outboundAdded": "تمت إضافة صادر NordVPN",
+        "outboundUpdated": "تم تحديث صادر NordVPN"
+      },
+      "warp": {
+        "licenseError": "فشل تعيين رخصة WARP.",
+        "fetchFirst": "احصل على تكوين WARP أولاً.",
+        "createAccount": "إنشاء حساب WARP",
+        "accessToken": "Access token",
+        "deviceId": "معرف الجهاز",
+        "licenseKey": "مفتاح الرخصة",
+        "privateKey": "المفتاح الخاص",
+        "deleteAccount": "حذف الحساب",
+        "settings": "الإعدادات",
+        "licenseKeyLabel": "مفتاح رخصة WARP / WARP+",
+        "key": "المفتاح",
+        "keyPlaceholder": "مفتاح WARP+ مكوّن من 26 حرفاً",
+        "accountInfo": "معلومات الحساب",
+        "deviceName": "اسم الجهاز",
+        "deviceModel": "طراز الجهاز",
+        "deviceEnabled": "الجهاز مفعّل",
+        "accountType": "نوع الحساب",
+        "role": "الدور",
+        "warpPlusData": "بيانات WARP+",
+        "quota": "الحصة",
+        "usage": "الاستخدام",
+        "addOutbound": "إضافة صادر"
+      },
       "dns": {
       "dns": {
         "enable": "فعل DNS",
         "enable": "فعل DNS",
         "enableDesc": "فعل سيرفر DNS المدمج",
         "enableDesc": "فعل سيرفر DNS المدمج",
@@ -911,7 +1328,7 @@
         "strategyDesc": "الاستراتيجية العامة لحل أسماء الدومين",
         "strategyDesc": "الاستراتيجية العامة لحل أسماء الدومين",
         "add": "أضف سيرفر",
         "add": "أضف سيرفر",
         "edit": "عدل السيرفر",
         "edit": "عدل السيرفر",
-        "domains": "الدومينات",
+        "domains": "النطاقات",
         "expectIPs": "العناوين المتوقعة",
         "expectIPs": "العناوين المتوقعة",
         "unexpectIPs": "عناوين IP غير متوقعة",
         "unexpectIPs": "عناوين IP غير متوقعة",
         "useSystemHosts": "استخدام ملف Hosts الخاص بالنظام",
         "useSystemHosts": "استخدام ملف Hosts الخاص بالنظام",
@@ -992,16 +1409,16 @@
       "2faFailed": "فشل 2FA",
       "2faFailed": "فشل 2FA",
       "report": "🕰 التقارير المجدولة: {{ .RunTime }}\r\n",
       "report": "🕰 التقارير المجدولة: {{ .RunTime }}\r\n",
       "datetime": "⏰ التاريخ والوقت: {{ .DateTime }}\r\n",
       "datetime": "⏰ التاريخ والوقت: {{ .DateTime }}\r\n",
-      "hostname": "💻 السيرفر: {{ .Hostname }}\r\n",
+      "hostname": "💻 المضيف: {{ .Hostname }}\r\n",
       "version": "🚀 نسخة 3X-UI: {{ .Version }}\r\n",
       "version": "🚀 نسخة 3X-UI: {{ .Version }}\r\n",
       "xrayVersion": "📡 نسخة Xray: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 نسخة Xray: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
-      "ips": "🔢 عناوين IP:\r\n{{ .IPs }}\r\n",
+      "ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ وقت التشغيل: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ وقت التشغيل: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 تحميل النظام: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 تحميل النظام: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 الرام: {{ .Current }}/{{ .Total }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
       "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
       "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
       "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 الترافيك: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 الترافيك: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
@@ -1009,17 +1426,17 @@
       "username": "👤 اسم المستخدم: {{ .Username }}\r\n",
       "username": "👤 اسم المستخدم: {{ .Username }}\r\n",
       "reason": "❗️ السبب: {{ .Reason }}\r\n",
       "reason": "❗️ السبب: {{ .Reason }}\r\n",
       "time": "⏰ الوقت: {{ .Time }}\r\n",
       "time": "⏰ الوقت: {{ .Time }}\r\n",
-      "inbound": "📍 الإدخال: {{ .Remark }}\r\n",
-      "port": "🔌 البورت: {{ .Port }}\r\n",
+      "inbound": "📍 الوارد: {{ .Remark }}\r\n",
+      "port": "🔌 المنفذ: {{ .Port }}\r\n",
       "expire": "📅 تاريخ الانتهاء: {{ .Time }}\r\n",
       "expire": "📅 تاريخ الانتهاء: {{ .Time }}\r\n",
       "expireIn": "📅 هيخلص بعد: {{ .Time }}\r\n",
       "expireIn": "📅 هيخلص بعد: {{ .Time }}\r\n",
       "active": "💡 مفعل: {{ .Enable }}\r\n",
       "active": "💡 مفعل: {{ .Enable }}\r\n",
       "enabled": "🚨 مفعل: {{ .Enable }}\r\n",
       "enabled": "🚨 مفعل: {{ .Enable }}\r\n",
       "online": "🌐 حالة الاتصال: {{ .Status }}\r\n",
       "online": "🌐 حالة الاتصال: {{ .Status }}\r\n",
       "lastOnline": "🔙 آخر متصل: {{ .Time }}\r\n",
       "lastOnline": "🔙 آخر متصل: {{ .Time }}\r\n",
-      "email": "📧 الإيميل: {{ .Email }}\r\n",
-      "upload": "🔼 رفع: ↑{{ .Upload }}\r\n",
-      "download": "🔽 تنزيل: ↓{{ .Download }}\r\n",
+      "email": "📧 البريد: {{ .Email }}\r\n",
+      "upload": "🔼 الرفع: ↑{{ .Upload }}\r\n",
+      "download": "🔽 التنزيل: ↓{{ .Download }}\r\n",
       "total": "📊 الإجمالي: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "total": "📊 الإجمالي: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 مستخدم Telegram: {{ .TelegramID }}\r\n",
       "TGUser": "👤 مستخدم Telegram: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 نفذ {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 نفذ {{ .Type }}:\r\n",
@@ -1030,7 +1447,7 @@
       "backupTime": "🗄 وقت النسخة الاحتياطية: {{ .Time }}\r\n",
       "backupTime": "🗄 وقت النسخة الاحتياطية: {{ .Time }}\r\n",
       "refreshedOn": "\r\n📋🔄 اتحدّث في: {{ .Time }}\r\n\r\n",
       "refreshedOn": "\r\n📋🔄 اتحدّث في: {{ .Time }}\r\n\r\n",
       "yes": "✅ أيوه",
       "yes": "✅ أيوه",
-      "no": "❌ لأ",
+      "no": "❌ لا",
       "received_id": "🔑📥 الـ ID اتحدث.",
       "received_id": "🔑📥 الـ ID اتحدث.",
       "received_password": "🔑📥 الباسورد اتحدث.",
       "received_password": "🔑📥 الباسورد اتحدث.",
       "received_email": "📧📥 الإيميل اتحدث.",
       "received_email": "📧📥 الإيميل اتحدث.",
@@ -1042,7 +1459,7 @@
       "inbound_client_data_id": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 المعرف: {{ .ClientId }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
       "inbound_client_data_id": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 المعرف: {{ .ClientId }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
       "inbound_client_data_pass": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 كلمة المرور: {{ .ClientPass }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
       "inbound_client_data_pass": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 كلمة المرور: {{ .ClientPass }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
       "cancel": "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄",
       "cancel": "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄",
-      "error_add_client": "⚠️ حصل خطأ:\n\n {{ .error }}",
+      "error_add_client": "⚠️ خطأ:\n\n {{ .error }}",
       "using_default_value": "تمام، هشيل على القيمة الافتراضية. 😊",
       "using_default_value": "تمام، هشيل على القيمة الافتراضية. 😊",
       "incorrect_input": "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫",
       "incorrect_input": "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫",
       "AreYouSure": "إنت متأكد؟ 🤔",
       "AreYouSure": "إنت متأكد؟ 🤔",
@@ -1087,11 +1504,11 @@
       "submitDisable": "إرسال كمعطّل ☑️",
       "submitDisable": "إرسال كمعطّل ☑️",
       "submitEnable": "إرسال كمفعّل ✅",
       "submitEnable": "إرسال كمفعّل ✅",
       "use_default": "🏷️ استخدام الإعدادات الافتراضية",
       "use_default": "🏷️ استخدام الإعدادات الافتراضية",
-      "change_id": "⚙️🔑 المعرّف",
+      "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 كلمة السر",
       "change_password": "⚙️🔑 كلمة السر",
-      "change_email": "⚙️📧 البريد الإلكتروني",
+      "change_email": "⚙️📧 البريد",
       "change_comment": "⚙️💬 تعليق",
       "change_comment": "⚙️💬 تعليق",
-      "change_flow": "⚙️🚦 التدفق",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "إعادة ضبط جميع الترافيك",
       "ResetAllTraffics": "إعادة ضبط جميع الترافيك",
       "SortedTrafficUsageReport": "تقرير استخدام الترافيك المرتب"
       "SortedTrafficUsageReport": "تقرير استخدام الترافيك المرتب"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "اختار الإدخال"
       "chooseInbound": "اختار الإدخال"
     }
     }
   }
   }
-}
+}

+ 299 - 3
web/translation/en-US.json

@@ -396,7 +396,6 @@
       },
       },
       "telegramDesc": "Please provide Telegram Chat ID. (use '/id' command in the bot) or ({'@'}userinfobot)",
       "telegramDesc": "Please provide Telegram Chat ID. (use '/id' command in the bot) or ({'@'}userinfobot)",
       "subscriptionDesc": "To find your subscription URL, navigate to the 'Details'. Additionally, you can use the same name for several clients.",
       "subscriptionDesc": "To find your subscription URL, navigate to the 'Details'. Additionally, you can use the same name for several clients.",
-      "info": "Info",
       "same": "Same",
       "same": "Same",
       "inboundData": "Inbound's Data",
       "inboundData": "Inbound's Data",
       "exportInbound": "Export Inbound",
       "exportInbound": "Export Inbound",
@@ -433,6 +432,139 @@
         "getNewmldsa65Error": "Error while obtaining mldsa65.",
         "getNewmldsa65Error": "Error while obtaining mldsa65.",
         "getNewVlessEncError": "Error while obtaining VlessEnc."
         "getNewVlessEncError": "Error while obtaining VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Move up",
+        "moveDown": "Move down",
+        "addAll": "Add all",
+        "addAllFallbackTooltip": "Add a fallback row for every eligible inbound not yet wired up",
+        "peers": "Peers",
+        "addPeer": "Add peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Windows-only. CIDRs added to the system routing table automatically so matching traffic goes through TUN.",
+        "autoOutboundsInterface": "Auto outbounds interface",
+        "autoOutboundsInterfaceTooltip": "Physical interface for outbound traffic. Use 'auto' to detect; auto-enabled when Auto system routes is set.",
+        "rewriteAddress": "Rewrite address",
+        "rewritePort": "Rewrite port",
+        "allowedNetwork": "Allowed network",
+        "followRedirect": "Follow redirect",
+        "accounts": "Accounts",
+        "allowTransparent": "Allow transparent",
+        "encryptionMethod": "Encryption method",
+        "visionTestseed": "Vision testseed",
+        "version": "Version",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "Masquerade",
+        "type": "Type",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Rewrite Host",
+        "skipTlsVerify": "Skip TLS verify",
+        "directory": "Directory",
+        "statusCode": "Status code",
+        "body": "Body",
+        "headers": "Headers",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Request version",
+        "requestMethod": "Request method",
+        "requestPath": "Request path",
+        "requestHeaders": "Request headers",
+        "responseVersion": "Response version",
+        "responseStatus": "Response status",
+        "responseReason": "Response reason",
+        "responseHeaders": "Response headers",
+        "heartbeatPeriod": "Heartbeat Period",
+        "serviceName": "Service Name",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Max Buffered Upload",
+        "maxUploadSize": "Max Upload Size (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Server Max Header Bytes",
+        "paddingBytes": "Padding Bytes",
+        "uplinkHttpMethod": "Uplink HTTP Method",
+        "paddingObfsMode": "Padding Obfs Mode",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding Placement",
+        "paddingMethod": "Padding Method",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "No SSE Header",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Uplink (MB/s)",
+        "downlinkMbps": "Downlink (MB/s)",
+        "cwndMultiplier": "CWND Multiplier",
+        "maxSendingWindow": "Max Sending Window",
+        "externalProxy": "External Proxy",
+        "sniPlaceholder": "SNI (defaults to host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Default",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "V6 Only",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "Trusted X-Forwarded-For",
+        "addressPortStrategy": "Address+port strategy",
+        "tryDelayMs": "Try delay (ms)",
+        "prioritizeIPv6": "Prioritize IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Max concurrent try",
+        "customSockopt": "Custom sockopt",
+        "addCustomOption": "Add custom option",
+        "serverNameIndication": "Server Name Indication",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Auto",
+        "minMaxVersion": "Min/Max Version",
+        "rejectUnknownSni": "Reject Unknown SNI",
+        "disableSystemRoot": "Disable System Root",
+        "sessionResumption": "Session Resumption",
+        "oneTimeLoading": "One Time Loading",
+        "usageOption": "Usage Option",
+        "buildChain": "Build Chain",
+        "echKey": "ECH key",
+        "echConfig": "ECH config",
+        "getNewEchCert": "Get New ECH Cert",
+        "show": "Show",
+        "xver": "Xver",
+        "target": "Target",
+        "maxTimeDiff": "Max Time Diff (ms)",
+        "minClientVer": "Min Client Ver",
+        "maxClientVer": "Max Client Ver",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Get New Cert",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Get New Seed"
+      },
+      "info": {
+        "mode": "Mode",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Interface name",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Outbounds interface",
+        "autoSystemRoutes": "Auto system routes",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "No-kernel TUN",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Peer {n} config"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Request",
           "request": "Request",
@@ -777,6 +909,8 @@
       "subEnable": "Subscription Service",
       "subEnable": "Subscription Service",
       "subEnableDesc": "Enable/Disable the subscription service.",
       "subEnableDesc": "Enable/Disable the subscription service.",
       "subJsonEnable": "Enable/Disable the JSON subscription endpoint independently.",
       "subJsonEnable": "Enable/Disable the JSON subscription endpoint independently.",
+      "subJsonEnableTitle": "JSON subscription",
+      "subClashEnableTitle": "Clash / Mihomo subscription",
       "subTitle": "Subscription Title",
       "subTitle": "Subscription Title",
       "subTitleDesc": "Title shown in VPN client",
       "subTitleDesc": "Title shown in VPN client",
       "subSupportUrl": "Support URL",
       "subSupportUrl": "Support URL",
@@ -822,6 +956,54 @@
       "fragmentSett": "Fragmentation Settings",
       "fragmentSett": "Fragmentation Settings",
       "noisesDesc": "Enable Noises.",
       "noisesDesc": "Enable Noises.",
       "noisesSett": "Noises Settings",
       "noisesSett": "Noises Settings",
+      "trustedProxyCidrs": "Trusted proxy CIDRs",
+      "trustedProxyCidrsDesc": "Comma-separated IPs/CIDRs allowed to set forwarded host, proto, and client IP headers.",
+      "ldap": {
+        "enable": "Enable LDAP sync",
+        "host": "LDAP host",
+        "port": "LDAP port",
+        "useTls": "Use TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Configured; leave blank to keep current password.",
+        "passwordUnconfigured": "Not configured.",
+        "passwordPlaceholder": "Configured - enter a new value to replace",
+        "baseDn": "Base DN",
+        "userFilter": "User filter",
+        "userAttr": "User attribute (username/email)",
+        "vlessField": "VLESS flag attribute",
+        "flagField": "Generic flag attribute (optional)",
+        "flagFieldDesc": "If set, overrides VLESS flag — e.g. shadowInactive.",
+        "truthyValues": "Truthy values",
+        "truthyValuesDesc": "Comma-separated; default: true,1,yes,on",
+        "invertFlag": "Invert flag",
+        "invertFlagDesc": "Enable when the attribute means disabled (e.g. shadowInactive).",
+        "syncSchedule": "Sync schedule",
+        "syncScheduleDesc": "Cron-like string, e.g. @every 1m",
+        "inboundTags": "Inbound tags",
+        "inboundTagsDesc": "Inbounds that LDAP sync may auto-create or auto-delete clients on.",
+        "noInbounds": "No inbounds found. Create one in Inbounds first.",
+        "autoCreate": "Auto create clients",
+        "autoDelete": "Auto delete clients",
+        "defaultTotalGb": "Default total (GB)",
+        "defaultExpiryDays": "Default expiry (days)",
+        "defaultIpLimit": "Default IP limit"
+      },
+      "subFormats": {
+        "packets": "Packets",
+        "length": "Length",
+        "interval": "Interval",
+        "maxSplit": "Max split",
+        "noises": "Noises",
+        "noiseItem": "Noise №{n}",
+        "type": "Type",
+        "packet": "Packet",
+        "delayMs": "Delay (ms)",
+        "applyTo": "Apply to",
+        "addNoise": "+ Noise",
+        "concurrency": "Concurrency",
+        "xudpConcurrency": "xudp concurrency",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Transmit multiple independent data streams within an established data stream.",
       "muxDesc": "Transmit multiple independent data streams within an established data stream.",
       "muxSett": "Mux Settings",
       "muxSett": "Mux Settings",
@@ -877,6 +1059,9 @@
       "save": "Save",
       "save": "Save",
       "restart": "Restart Xray",
       "restart": "Restart Xray",
       "restartSuccess": "Xray has been successfully relaunched.",
       "restartSuccess": "Xray has been successfully relaunched.",
+      "restartOutputTitle": "Xray restart output",
+      "restartConfirmTitle": "Restart xray?",
+      "restartConfirmContent": "Reloads the xray service with the saved configuration.",
       "stopSuccess": "Xray has been successfully stopped.",
       "stopSuccess": "Xray has been successfully stopped.",
       "restartError": "There was an error when rebooting the Xray.",
       "restartError": "There was an error when rebooting the Xray.",
       "stopError": "There was an error when stopping the Xray.",
       "stopError": "There was an error when stopping the Xray.",
@@ -951,7 +1136,74 @@
         "info": "Info",
         "info": "Info",
         "add": "Add Rule",
         "add": "Add Rule",
         "edit": "Edit Rule",
         "edit": "Edit Rule",
-        "useComma": "Comma-separated items"
+        "useComma": "Comma-separated list"
+      },
+      "routing": {
+        "dragToReorder": "Drag to reorder"
+      },
+      "ruleForm": {
+        "sourceIps": "Source IPs",
+        "sourcePort": "Source port",
+        "vlessRoute": "VLESS route",
+        "attributes": "Attributes",
+        "value": "Value",
+        "user": "User",
+        "inboundTags": "Inbound tags",
+        "outboundTag": "Outbound tag",
+        "balancerTag": "Balancer tag",
+        "balancerTagTooltip": "Routes traffic through one of the configured load balancers"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Tag already used by another outbound",
+        "tagRequired": "Tag is required",
+        "tagPlaceholder": "unique-tag",
+        "localIpPlaceholder": "local IP",
+        "addressRequired": "Address is required",
+        "portRequired": "Port is required",
+        "optional": "optional",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "UoT version",
+        "inboundTag": "Inbound tag",
+        "inboundTagPlaceholder": "inbound tag used in routing rules",
+        "responseType": "Response type",
+        "rewriteNetwork": "Rewrite network",
+        "unchanged": "(unchanged)",
+        "unchangedAddress": "(unchanged) e.g. 1.1.1.1",
+        "rules": "Rules",
+        "ruleN": "Rule {n}",
+        "action": "Action",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Final Rules",
+        "overrideXrayPrivateIp": "Override Xray's default private-IP block",
+        "blockDelay": "Block delay (ms)",
+        "reverseSniffing": "Reverse Sniffing",
+        "workers": "Workers",
+        "reserved": "Reserved",
+        "minUploadInterval": "Min upload interval (ms)",
+        "maxUploadSizeBytes": "Max upload size (bytes)",
+        "uplinkChunkSize": "Uplink chunk size",
+        "noGrpcHeader": "No gRPC header",
+        "maxConcurrency": "Max concurrency",
+        "maxConnections": "Max connections",
+        "maxReuseTimes": "Max reuse times",
+        "maxRequestTimes": "Max request times",
+        "maxReusableSecs": "Max reusable secs",
+        "keepAlivePeriod": "Keep alive period",
+        "authPassword": "Auth password",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "server name",
+        "verifyPeerName": "Verify peer name",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Keep alive interval",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Interface",
+        "ipv6Only": "IPv6 only",
+        "acceptProxyProtocol": "Accept proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
       },
       },
       "outbound": {
       "outbound": {
         "addOutbound": "Add Outbound",
         "addOutbound": "Add Outbound",
@@ -981,6 +1233,8 @@
         "testSuccess": "Test successful",
         "testSuccess": "Test successful",
         "testFailed": "Test failed",
         "testFailed": "Test failed",
         "testError": "Failed to test outbound",
         "testError": "Failed to test outbound",
+        "testModeTooltip": "TCP: fast dial-only probe. HTTP: full request through xray.",
+        "testAll": "Test all",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Access Token",
         "accessToken": "Access Token",
         "country": "Country",
         "country": "Country",
@@ -997,6 +1251,16 @@
         "balancerSelectors": "Selectors",
         "balancerSelectors": "Selectors",
         "tag": "Tag",
         "tag": "Tag",
         "tagDesc": "Unique Tag",
         "tagDesc": "Unique Tag",
+        "tagDuplicate": "Tag already used by another balancer",
+        "tagPlaceholder": "unique balancer tag",
+        "selector": "Selector",
+        "fallback": "Fallback",
+        "expected": "Expected",
+        "expectedPlaceholder": "optimal node count",
+        "maxRtt": "Max RTT",
+        "tolerance": "Tolerance",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "It is not possible to use balancerTag and outboundTag at the same time. If used at the same time, only outboundTag will work."
         "balancerDesc": "It is not possible to use balancerTag and outboundTag at the same time. If used at the same time, only outboundTag will work."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -1013,6 +1277,38 @@
         "userLevel": "User Level",
         "userLevel": "User Level",
         "userLevelDesc": "All connections made through this inbound will use this user level. Default is 0"
         "userLevelDesc": "All connections made through this inbound will use this user level. Default is 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Private key",
+        "noServers": "No servers found for the selected country",
+        "noPublicKey": "Selected server does not advertise a NordLynx public key.",
+        "outboundAdded": "NordVPN outbound added",
+        "outboundUpdated": "NordVPN outbound updated"
+      },
+      "warp": {
+        "licenseError": "Failed to set WARP license.",
+        "fetchFirst": "Fetch the WARP config first.",
+        "createAccount": "Create WARP account",
+        "accessToken": "Access token",
+        "deviceId": "Device ID",
+        "licenseKey": "License key",
+        "privateKey": "Private key",
+        "deleteAccount": "Delete account",
+        "settings": "Settings",
+        "licenseKeyLabel": "WARP / WARP+ license key",
+        "key": "Key",
+        "keyPlaceholder": "26-char WARP+ key",
+        "accountInfo": "Account info",
+        "deviceName": "Device name",
+        "deviceModel": "Device model",
+        "deviceEnabled": "Device enabled",
+        "accountType": "Account type",
+        "role": "Role",
+        "warpPlusData": "WARP+ data",
+        "quota": "Quota",
+        "usage": "Usage",
+        "addOutbound": "Add outbound"
+      },
       "dns": {
       "dns": {
         "enable": "Enable DNS",
         "enable": "Enable DNS",
         "enableDesc": "Enable built-in DNS server",
         "enableDesc": "Enable built-in DNS server",
@@ -1240,4 +1536,4 @@
       "chooseInbound": "Choose an Inbound"
       "chooseInbound": "Choose an Inbound"
     }
     }
   }
   }
-}
+}

+ 466 - 49
web/translation/es-ES.json

@@ -8,15 +8,22 @@
   "save": "Guardar",
   "save": "Guardar",
   "logout": "Cerrar Sesión",
   "logout": "Cerrar Sesión",
   "create": "Crear",
   "create": "Crear",
+  "add": "Añadir",
+  "remove": "Quitar",
   "update": "Actualizar",
   "update": "Actualizar",
   "copy": "Copiar",
   "copy": "Copiar",
   "copied": "Copiado",
   "copied": "Copiado",
+  "more": "más",
   "download": "Descargar",
   "download": "Descargar",
   "remark": "Notas",
   "remark": "Notas",
   "enable": "Habilitar",
   "enable": "Habilitar",
   "protocol": "Protocolo",
   "protocol": "Protocolo",
   "search": "Buscar",
   "search": "Buscar",
   "filter": "Filtrar",
   "filter": "Filtrar",
+  "all": "Todos",
+  "from": "Desde",
+  "to": "Hasta",
+  "done": "Hecho",
   "loading": "Cargando...",
   "loading": "Cargando...",
   "refresh": "Actualizar",
   "refresh": "Actualizar",
   "clear": "Borrar",
   "clear": "Borrar",
@@ -27,7 +34,7 @@
   "check": "Verificar",
   "check": "Verificar",
   "indefinite": "Indefinido",
   "indefinite": "Indefinido",
   "unlimited": "Ilimitado",
   "unlimited": "Ilimitado",
-  "none": "None",
+  "none": "Ninguno",
   "qrCode": "Código QR",
   "qrCode": "Código QR",
   "info": "Más Información",
   "info": "Más Información",
   "edit": "Editar",
   "edit": "Editar",
@@ -40,15 +47,15 @@
   "useIPv4ForHost": "Usar IPv4 para el host",
   "useIPv4ForHost": "Usar IPv4 para el host",
   "transmission": "Transmisión",
   "transmission": "Transmisión",
   "host": "Host",
   "host": "Host",
-  "path": "Path",
-  "camouflage": "Camuflaje",
+  "path": "Ruta",
+  "camouflage": "Ofuscación",
   "status": "Estado",
   "status": "Estado",
   "enabled": "Habilitado",
   "enabled": "Habilitado",
   "disabled": "Deshabilitado",
   "disabled": "Deshabilitado",
   "depleted": "Agotado",
   "depleted": "Agotado",
   "depletingSoon": "Agotándose",
   "depletingSoon": "Agotándose",
-  "offline": "fuera de línea",
-  "online": "en línea",
+  "offline": "Sin conexión",
+  "online": "En línea",
   "domainName": "Nombre de dominio",
   "domainName": "Nombre de dominio",
   "monitor": "Listening IP",
   "monitor": "Listening IP",
   "certificate": "Certificado Digital",
   "certificate": "Certificado Digital",
@@ -97,9 +104,10 @@
     "dashboard": "Estado del Sistema",
     "dashboard": "Estado del Sistema",
     "inbounds": "Entradas",
     "inbounds": "Entradas",
     "clients": "Clientes",
     "clients": "Clientes",
+    "groups": "Grupos",
     "nodes": "Nodos",
     "nodes": "Nodos",
-    "settings": "Configuraciones",
-    "xray": "Ajustes Xray",
+    "settings": "Ajustes del panel",
+    "xray": "Configuración Xray",
     "apiDocs": "Documentación de la API",
     "apiDocs": "Documentación de la API",
     "logout": "Cerrar Sesión",
     "logout": "Cerrar Sesión",
     "link": "Gestionar",
     "link": "Gestionar",
@@ -123,7 +131,7 @@
       "cpu": "CPU",
       "cpu": "CPU",
       "logicalProcessors": "Procesadores lógicos",
       "logicalProcessors": "Procesadores lógicos",
       "frequency": "Frecuencia",
       "frequency": "Frecuencia",
-      "swap": "Memoria Virtual",
+      "swap": "Swap",
       "storage": "Almacenamiento",
       "storage": "Almacenamiento",
       "memory": "RAM",
       "memory": "RAM",
       "threads": "Hilos",
       "threads": "Hilos",
@@ -166,7 +174,7 @@
       "toggleIpVisibility": "Alternar visibilidad de la IP",
       "toggleIpVisibility": "Alternar visibilidad de la IP",
       "overallSpeed": "Velocidad general",
       "overallSpeed": "Velocidad general",
       "upload": "Subida",
       "upload": "Subida",
-      "download": "Descarga",
+      "download": "Descargar",
       "totalData": "Datos totales",
       "totalData": "Datos totales",
       "sent": "Enviado",
       "sent": "Enviado",
       "received": "Recibido",
       "received": "Recibido",
@@ -228,7 +236,7 @@
       "dontRefresh": "La instalación está en progreso, por favor no actualices esta página.",
       "dontRefresh": "La instalación está en progreso, por favor no actualices esta página.",
       "logs": "Registros",
       "logs": "Registros",
       "config": "Configuración",
       "config": "Configuración",
-      "backup": "Сopia de Seguridad",
+      "backup": "Copia de seguridad",
       "backupTitle": "Copia & Restauración",
       "backupTitle": "Copia & Restauración",
       "exportDatabase": "Copia de seguridad",
       "exportDatabase": "Copia de seguridad",
       "exportDatabaseDesc": "Haz clic para descargar un archivo .db que contiene una copia de seguridad de tu base de datos actual en tu dispositivo.",
       "exportDatabaseDesc": "Haz clic para descargar un archivo .db que contiene una copia de seguridad de tu base de datos actual en tu dispositivo.",
@@ -270,14 +278,14 @@
       },
       },
       "protocol": "Protocolo",
       "protocol": "Protocolo",
       "port": "Puerto",
       "port": "Puerto",
-      "portMap": "Puertos de Destino",
+      "portMap": "Asignación de puertos",
       "traffic": "Tráfico",
       "traffic": "Tráfico",
       "details": "Detalles",
       "details": "Detalles",
       "transportConfig": "Transporte",
       "transportConfig": "Transporte",
       "expireDate": "Fecha de Expiración",
       "expireDate": "Fecha de Expiración",
       "createdAt": "Creado",
       "createdAt": "Creado",
       "updatedAt": "Actualizado",
       "updatedAt": "Actualizado",
-      "resetTraffic": "Restablecer Tráfico",
+      "resetTraffic": "Restablecer tráfico",
       "addInbound": "Agregar Entrada",
       "addInbound": "Agregar Entrada",
       "generalActions": "Acciones Generales",
       "generalActions": "Acciones Generales",
       "modifyInbound": "Modificar Entrada",
       "modifyInbound": "Modificar Entrada",
@@ -292,11 +300,29 @@
       "delAllClients": "Eliminar todos los clientes",
       "delAllClients": "Eliminar todos los clientes",
       "delAllClientsConfirmTitle": "¿Eliminar los {count} clientes de \"{remark}\"?",
       "delAllClientsConfirmTitle": "¿Eliminar los {count} clientes de \"{remark}\"?",
       "delAllClientsConfirmContent": "Elimina todos los clientes de este inbound y sus registros de tráfico. El inbound se mantiene. Esto no se puede deshacer.",
       "delAllClientsConfirmContent": "Elimina todos los clientes de este inbound y sus registros de tráfico. El inbound se mantiene. Esto no se puede deshacer.",
+      "attachClients": "Asociar clientes a…",
+      "addClientsToGroup": "Añadir clientes al grupo…",
+      "attachClientsTitle": "Asociar clientes desde «{remark}»",
+      "attachClientsDesc": "Asocia los mismos {count} cliente(s) (mismo UUID/contraseña y tráfico compartido) a las entradas seleccionadas. Permanecen también en esta entrada.",
+      "attachClientsTargets": "Entradas objetivo",
+      "attachClientsNoTargets": "No hay otras entradas compatibles disponibles para asociar.",
+      "attachClientsResult": "Asociados {attached}, omitidos {skipped}.",
+      "attachClientsResultMixed": "Asociados {attached}, omitidos {skipped}, errores {errors}.",
+      "attachClientsSelectLabel": "Clientes para asociar",
+      "attachClientsSearchPlaceholder": "Buscar email o comentario",
+      "attachClientsStatusDisabled": "Deshabilitado",
+      "attachClientsSelectedCount": "{selected} de {total} seleccionado(s)",
+      "detachClients": "Desasociar clientes",
+      "detachClientsTitle": "Desasociar clientes de «{remark}»",
+      "detachClientsDesc": "Quita el cliente o clientes seleccionados solo de esta entrada. Los registros se conservan (usa Delete para eliminar por completo). El origen tiene {count} cliente(s) en total.",
+      "detachClientsResult": "Desasociados {detached}, omitidos {skipped}.",
+      "detachClientsResultMixed": "Desasociados {detached}, omitidos {skipped}, errores {errors}.",
+      "detachClientsSelectLabel": "Clientes para desasociar",
       "exportLinksTitle": "Exportar enlaces del inbound",
       "exportLinksTitle": "Exportar enlaces del inbound",
       "exportSubsTitle": "Exportar enlaces de suscripción",
       "exportSubsTitle": "Exportar enlaces de suscripción",
       "exportAllLinksTitle": "Exportar todos los enlaces de inbound",
       "exportAllLinksTitle": "Exportar todos los enlaces de inbound",
       "exportAllSubsTitle": "Exportar todos los enlaces de suscripción",
       "exportAllSubsTitle": "Exportar todos los enlaces de suscripción",
-      "inboundJsonTitle": "JSON del inbound",
+      "inboundJsonTitle": "JSON de entrada",
       "deleteClient": "Eliminar cliente",
       "deleteClient": "Eliminar cliente",
       "deleteClientContent": "¿Está seguro de que desea eliminar el cliente?",
       "deleteClientContent": "¿Está seguro de que desea eliminar el cliente?",
       "resetTrafficContent": "¿Confirmar restablecimiento de tráfico?",
       "resetTrafficContent": "¿Confirmar restablecimiento de tráfico?",
@@ -306,7 +332,7 @@
       "destinationPort": "Puerto de Destino",
       "destinationPort": "Puerto de Destino",
       "targetAddress": "Dirección de Destino",
       "targetAddress": "Dirección de Destino",
       "monitorDesc": "Dejar en blanco por defecto",
       "monitorDesc": "Dejar en blanco por defecto",
-      "meansNoLimit": " = illimitata. (unidad: GB)",
+      "meansNoLimit": "= Ilimitado. (unidad: GB)",
       "totalFlow": "Flujo Total",
       "totalFlow": "Flujo Total",
       "leaveBlankToNeverExpire": "Dejar en Blanco para Nunca Expirar",
       "leaveBlankToNeverExpire": "Dejar en Blanco para Nunca Expirar",
       "noRecommendKeepDefault": "No hay requisitos especiales para mantener la configuración predeterminada",
       "noRecommendKeepDefault": "No hay requisitos especiales para mantener la configuración predeterminada",
@@ -341,6 +367,7 @@
       "IPLimitlogDesc": "Registro de historial de IPs (antes de habilitar la entrada después de que haya sido desactivada por el límite de IP, debes borrar el registro).",
       "IPLimitlogDesc": "Registro de historial de IPs (antes de habilitar la entrada después de que haya sido desactivada por el límite de IP, debes borrar el registro).",
       "IPLimitlogclear": "Limpiar el Registro",
       "IPLimitlogclear": "Limpiar el Registro",
       "setDefaultCert": "Establecer certificado desde el panel",
       "setDefaultCert": "Establecer certificado desde el panel",
+      "setDefaultCertEmpty": "No hay certificado configurado para el panel. Configura uno en Ajustes primero.",
       "streamTab": "Stream",
       "streamTab": "Stream",
       "securityTab": "Seguridad",
       "securityTab": "Seguridad",
       "sniffingTab": "Sniffing",
       "sniffingTab": "Sniffing",
@@ -369,7 +396,6 @@
       },
       },
       "telegramDesc": "Por favor, proporciona el ID de Chat de Telegram. (usa el comando '/id' en el bot) o ({'@'}userinfobot)",
       "telegramDesc": "Por favor, proporciona el ID de Chat de Telegram. (usa el comando '/id' en el bot) o ({'@'}userinfobot)",
       "subscriptionDesc": "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones.",
       "subscriptionDesc": "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones.",
-      "info": "Info",
       "same": "misma",
       "same": "misma",
       "inboundData": "Datos de entrada",
       "inboundData": "Datos de entrada",
       "exportInbound": "Exportación entrante",
       "exportInbound": "Exportación entrante",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Error al obtener el certificado mldsa65.",
         "getNewmldsa65Error": "Error al obtener el certificado mldsa65.",
         "getNewVlessEncError": "Error al obtener el certificado VlessEnc."
         "getNewVlessEncError": "Error al obtener el certificado VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Subir",
+        "moveDown": "Bajar",
+        "addAll": "Añadir todo",
+        "addAllFallbackTooltip": "Añade una fila de fallback para cada entrada elegible aún no conectada",
+        "peers": "Peers",
+        "addPeer": "Añadir peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Solo Windows. Los CIDR se añaden automáticamente a la tabla de enrutamiento del sistema para que el tráfico coincidente pase por TUN.",
+        "autoOutboundsInterface": "Interfaz de salidas automática",
+        "autoOutboundsInterfaceTooltip": "Interfaz física para tráfico de salida. Usa 'auto' para detectar; se habilita automáticamente cuando se establece Auto system routes.",
+        "rewriteAddress": "Reescribir dirección",
+        "rewritePort": "Reescribir puerto",
+        "allowedNetwork": "Red permitida",
+        "followRedirect": "Seguir redirección",
+        "accounts": "Cuentas",
+        "allowTransparent": "Permitir transparente",
+        "encryptionMethod": "Método de cifrado",
+        "visionTestseed": "Vision testseed",
+        "version": "Versión",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "Masquerade",
+        "type": "Tipo",
+        "upstreamUrl": "URL Upstream",
+        "rewriteHost": "Reescribir Host",
+        "skipTlsVerify": "Saltar verificación TLS",
+        "directory": "Directorio",
+        "statusCode": "Código de estado",
+        "body": "Body",
+        "headers": "Cabeceras",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Versión de petición",
+        "requestMethod": "Método de petición",
+        "requestPath": "Ruta de petición",
+        "requestHeaders": "Cabeceras de petición",
+        "responseVersion": "Versión de respuesta",
+        "responseStatus": "Estado de respuesta",
+        "responseReason": "Razón de respuesta",
+        "responseHeaders": "Cabeceras de respuesta",
+        "heartbeatPeriod": "Periodo de heartbeat",
+        "serviceName": "Nombre de servicio",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Máx. subida en búfer",
+        "maxUploadSize": "Tamaño máx. de subida (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Máx. bytes cabecera servidor",
+        "paddingBytes": "Bytes de Padding",
+        "uplinkHttpMethod": "Método HTTP Uplink",
+        "paddingObfsMode": "Modo obfs de Padding",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Ubicación de Padding",
+        "paddingMethod": "Método de Padding",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Sin cabecera SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Subida (MB/s)",
+        "downlinkMbps": "Bajada (MB/s)",
+        "cwndMultiplier": "Multiplicador CWND",
+        "maxSendingWindow": "Máx. ventana de envío",
+        "externalProxy": "Proxy externo",
+        "sniPlaceholder": "SNI (por defecto = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Por defecto",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Solo V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For de confianza",
+        "addressPortStrategy": "Estrategia dirección+puerto",
+        "tryDelayMs": "Retraso de intento (ms)",
+        "prioritizeIPv6": "Priorizar IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Máx. intentos simultáneos",
+        "customSockopt": "Sockopt personalizado",
+        "addCustomOption": "Añadir opción personalizada",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Auto",
+        "minMaxVersion": "Versión mín/máx",
+        "rejectUnknownSni": "Rechazar SNI desconocido",
+        "disableSystemRoot": "Deshabilitar System Root",
+        "sessionResumption": "Reanudación de sesión",
+        "oneTimeLoading": "Carga única",
+        "usageOption": "Opción de uso",
+        "buildChain": "Construir cadena",
+        "echKey": "ECH key",
+        "echConfig": "Config ECH",
+        "getNewEchCert": "Obtener nuevo cert ECH",
+        "show": "Mostrar",
+        "xver": "Xver",
+        "target": "Objetivo",
+        "maxTimeDiff": "Máx. diferencia de tiempo (ms)",
+        "minClientVer": "Mín. versión cliente",
+        "maxClientVer": "Máx. versión cliente",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Obtener nuevo cert",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Obtener nuevo Seed"
+      },
+      "info": {
+        "mode": "Modo",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Nombre de interfaz",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Interfaz de salidas",
+        "autoSystemRoutes": "Rutas del sistema automáticas",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN sin kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Config Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Pedido",
           "request": "Pedido",
@@ -416,7 +575,7 @@
         "tcp": {
         "tcp": {
           "version": "Versión",
           "version": "Versión",
           "method": "Método",
           "method": "Método",
-          "path": "Camino",
+          "path": "Ruta",
           "status": "Estado",
           "status": "Estado",
           "statusDescription": "Descripción de la Situación",
           "statusDescription": "Descripción de la Situación",
           "requestHeader": "Encabezado de solicitud",
           "requestHeader": "Encabezado de solicitud",
@@ -456,6 +615,20 @@
       "days": "Día(s)",
       "days": "Día(s)",
       "renew": "Renovación automática",
       "renew": "Renovación automática",
       "renewDesc": "Renovación automática tras la expiración. (0 = desactivado) (unidad: día)",
       "renewDesc": "Renovación automática tras la expiración. (0 = desactivado) (unidad: día)",
+      "searchPlaceholder": "Buscar email, comentario, sub ID, UUID, contraseña, auth…",
+      "filterTitle": "Filtrar clientes",
+      "clearAllFilters": "Limpiar todo",
+      "sortOldest": "Más antiguos",
+      "sortNewest": "Más recientes",
+      "sortRecentlyUpdated": "Recientemente actualizados",
+      "sortRecentlyOnline": "Recientemente en línea",
+      "sortEmailAZ": "Email A→Z",
+      "sortEmailZA": "Email Z→A",
+      "sortMostTraffic": "Mayor tráfico",
+      "sortHighestRemaining": "Mayor restante",
+      "sortExpiringSoonest": "Caducidad más próxima",
+      "has": "Tiene",
+      "hasNot": "No tiene",
       "title": "Clientes",
       "title": "Clientes",
       "actions": "Acciones",
       "actions": "Acciones",
       "totalGB": "Total enviado/recibido (GB)",
       "totalGB": "Total enviado/recibido (GB)",
@@ -465,10 +638,13 @@
       "password": "Contraseña",
       "password": "Contraseña",
       "subId": "ID de suscripción",
       "subId": "ID de suscripción",
       "online": "En línea",
       "online": "En línea",
-      "email": "Correo",
+      "email": "Email",
+      "group": "Grupo",
+      "groupDesc": "Etiqueta lógica para agrupar clientes relacionados (p. ej. equipo, cliente, región). Filtrable desde la barra de herramientas.",
+      "groupPlaceholder": "p. ej. customer-a",
       "comment": "Comentario",
       "comment": "Comentario",
       "traffic": "Tráfico",
       "traffic": "Tráfico",
-      "offline": "Desconectado",
+      "offline": "Sin conexión",
       "addTitle": "Añadir cliente",
       "addTitle": "Añadir cliente",
       "qrCode": "Código QR",
       "qrCode": "Código QR",
       "moreInformation": "Más información",
       "moreInformation": "Más información",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Restablecer tráfico de todos los clientes",
       "resetAllTraffics": "Restablecer tráfico de todos los clientes",
       "resetAllTrafficsTitle": "¿Restablecer tráfico de todos los clientes?",
       "resetAllTrafficsTitle": "¿Restablecer tráfico de todos los clientes?",
       "resetAllTrafficsContent": "El contador de subida/bajada de cada cliente vuelve a cero. Las cuotas y la expiración no se modifican. Esta acción no se puede deshacer.",
       "resetAllTrafficsContent": "El contador de subida/bajada de cada cliente vuelve a cero. Las cuotas y la expiración no se modifican. Esta acción no se puede deshacer.",
-      "empty": "Aún no hay clientes — añade uno para empezar.",
       "deleteConfirmTitle": "¿Eliminar al cliente {email}?",
       "deleteConfirmTitle": "¿Eliminar al cliente {email}?",
       "deleteConfirmContent": "Esto elimina al cliente de cada inbound asociado y descarta su registro de tráfico. No se puede deshacer.",
       "deleteConfirmContent": "Esto elimina al cliente de cada inbound asociado y descarta su registro de tráfico. No se puede deshacer.",
       "deleteSelected": "Eliminar ({count})",
       "deleteSelected": "Eliminar ({count})",
       "adjustSelected": "Ajustar ({count})",
       "adjustSelected": "Ajustar ({count})",
+      "subLinksSelected": "Enlaces sub ({count})",
+      "addToGroupTitle": "Añadir {count} cliente(s) a un grupo",
+      "addToGroupTooltip": "Selecciona un grupo existente o escribe un nombre nuevo. Usa Ungroup para quitar clientes de su grupo actual.",
+      "addToGroupPlaceholder": "Nombre del grupo",
+      "addToGroupSuccessToast": "Se añadieron {count} cliente(s) a {group}",
+      "ungroupSuccessToast": "Grupo limpiado de {count} cliente(s)",
+      "ungroup": "Desagrupar",
+      "ungroupConfirmTitle": "¿Quitar {count} cliente(s) de su grupo?",
+      "ungroupConfirmContent": "Limpia la etiqueta de grupo en cada cliente seleccionado. Los clientes se conservan (usa Delete para eliminarlos por completo).",
+      "addToGroup": "Añadir al grupo",
+      "attach": "Asociar",
+      "adjust": "Ajustar",
+      "subLinks": "Enlaces sub",
+      "selectedCount": "{count} seleccionado(s)",
+      "attachSelected": "Asociar ({count})",
+      "attachToInboundsTitle": "Asociar {count} cliente(s) a entrada(s)",
+      "attachToInboundsDesc": "Asocia los {count} cliente(s) seleccionados (mismo UUID/contraseña y tráfico compartido) a las entradas elegidas. Mantienen sus asociaciones existentes.",
+      "attachToInboundsTargets": "Entradas objetivo",
+      "attachToInboundsNoTargets": "No hay entradas multiusuario disponibles para asociar.",
+      "detachSelected": "Desasociar ({count})",
+      "detach": "Desasociar",
+      "detachFromInboundsTitle": "Desasociar {count} cliente(s) de entrada(s)",
+      "detachFromInboundsDesc": "Quita los {count} cliente(s) seleccionados de las entradas elegidas. Las parejas donde el cliente no estaba asociado se omiten silenciosamente. Los registros de los clientes se conservan (usa Delete para eliminar por completo).",
+      "detachFromInboundsTargets": "Entradas para desasociar",
+      "detachFromInboundsNoTargets": "No hay entradas multiusuario disponibles.",
+      "detachFromInboundsResult": "Desasociados {detached}, omitidos {skipped}.",
+      "detachFromInboundsResultMixed": "Desasociados {detached}, omitidos {skipped}, errores {errors}.",
+      "subLinksTitle": "Enlaces sub ({count})",
+      "subLinkColumn": "URL de suscripción",
+      "subJsonLinkColumn": "URL JSON de suscripción",
+      "subLinksCopyAll": "Copiar todo",
+      "subLinksCopiedAll": "Copiados {count} enlace(s)",
+      "subLinksEmpty": "Ninguno de los clientes seleccionados tiene ID de suscripción.",
+      "subLinksDisabled": "El servicio de suscripción está deshabilitado.",
+      "subLinksDisabledHint": "Habilita la suscripción en Ajustes del panel → Suscripción para generar enlaces.",
       "bulkDeleteConfirmTitle": "¿Eliminar {count} clientes?",
       "bulkDeleteConfirmTitle": "¿Eliminar {count} clientes?",
       "bulkDeleteConfirmContent": "Cada cliente seleccionado se elimina de los inbounds asociados y se descarta su registro de tráfico. No se puede deshacer.",
       "bulkDeleteConfirmContent": "Cada cliente seleccionado se elimina de los inbounds asociados y se descarta su registro de tráfico. No se puede deshacer.",
       "bulkAdjustTitle": "Ajustar {count} clientes",
       "bulkAdjustTitle": "Ajustar {count} clientes",
@@ -505,10 +715,11 @@
       "delDepletedConfirmTitle": "¿Eliminar clientes agotados?",
       "delDepletedConfirmTitle": "¿Eliminar clientes agotados?",
       "delDepletedConfirmContent": "Elimina todos los clientes con cuota agotada o expirados. No se puede deshacer.",
       "delDepletedConfirmContent": "Elimina todos los clientes con cuota agotada o expirados. No se puede deshacer.",
       "auth": "Auth",
       "auth": "Auth",
-      "hysteriaAuth": "Auth de Hysteria",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "Seguridad VMess",
+      "reverseTag": "Etiqueta inversa",
       "reverseTagPlaceholder": "Reverse tag opcional",
       "reverseTagPlaceholder": "Reverse tag opcional",
       "telegramId": "ID de usuario de Telegram",
       "telegramId": "ID de usuario de Telegram",
       "telegramIdPlaceholder": "ID numérico de usuario de Telegram (0 = ninguno)",
       "telegramIdPlaceholder": "ID numérico de usuario de Telegram (0 = ninguno)",
@@ -528,13 +739,51 @@
         "delDepleted": "{count} clientes agotados eliminados"
         "delDepleted": "{count} clientes agotados eliminados"
       }
       }
     },
     },
+    "groups": {
+      "title": "Grupos",
+      "name": "Nombre",
+      "clientCount": "Clientes en el grupo",
+      "totalGroups": "Total de grupos",
+      "totalGroupedClients": "Clientes con grupo",
+      "emptyGroups": "Grupos vacíos",
+      "addGroup": "Añadir grupo",
+      "createSuccess": "Grupo «{name}» creado.",
+      "rename": "Renombrar",
+      "renameTitle": "Renombrar {name}",
+      "renameCollision": "Ya existe un grupo llamado «{name}».",
+      "renameSuccess": "Grupo renombrado en {count} cliente(s).",
+      "deleteConfirmTitle": "¿Eliminar el grupo {name}?",
+      "deleteConfirmContent": "Esto elimina el grupo y limpia su etiqueta de {count} cliente(s). Los clientes en sí no se eliminan.",
+      "deleteSuccess": "Grupo limpiado de {count} cliente(s).",
+      "resetTraffic": "Restablecer tráfico",
+      "resetConfirmTitle": "¿Restablecer tráfico del grupo {name}?",
+      "resetConfirmContent": "Esto pone a cero up/down para los {count} cliente(s) de este grupo.",
+      "resetSuccess": "Tráfico restablecido en {count} cliente(s).",
+      "adjustSuccess": "Ajustados {count} cliente(s) en {name}.",
+      "emptyForAction": "Este grupo aún no tiene clientes.",
+      "deleteGroupOnly": "Eliminar grupo (conservar clientes)",
+      "deleteClients": "Eliminar clientes del grupo",
+      "deleteClientsConfirmTitle": "¿Eliminar todos los clientes en {name}?",
+      "deleteClientsConfirmContent": "Esto elimina permanentemente {count} cliente(s) junto con sus registros de tráfico. La etiqueta de grupo también se limpia. Esto no se puede deshacer.",
+      "deleteClientsSuccess": "Eliminados {count} cliente(s).",
+      "deleteClientsMixed": "{ok} eliminados, {failed} omitidos",
+      "addToGroup": "Añadir clientes…",
+      "addToGroupTitle": "Añadir clientes al grupo «{name}»",
+      "addToGroupDesc": "Selecciona clientes para añadir a este grupo. Mantienen sus asociaciones de entrada existentes; solo cambia la etiqueta de grupo. Los clientes que ya están en este grupo no se muestran.",
+      "addToGroupEmpty": "No hay otros clientes disponibles para añadir.",
+      "addToGroupResult": "Añadidos {count} cliente(s) a {name}.",
+      "removeFromGroup": "Quitar clientes…",
+      "removeFromGroupTitle": "Quitar clientes del grupo «{name}»",
+      "removeFromGroupDesc": "Selecciona miembros para quitar de este grupo. Los clientes se conservan (usa «Eliminar clientes del grupo» para eliminarlos por completo).",
+      "removeFromGroupResult": "Quitados {count} cliente(s) de {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Nodos",
       "title": "Nodos",
       "addNode": "Agregar nodo",
       "addNode": "Agregar nodo",
       "editNode": "Editar nodo",
       "editNode": "Editar nodo",
       "totalNodes": "Total de nodos",
       "totalNodes": "Total de nodos",
       "onlineNodes": "En línea",
       "onlineNodes": "En línea",
-      "offlineNodes": "Desconectado",
+      "offlineNodes": "Sin conexión",
       "avgLatency": "Latencia media",
       "avgLatency": "Latencia media",
       "name": "Nombre",
       "name": "Nombre",
       "namePlaceholder": "p. ej. de-frankfurt-1",
       "namePlaceholder": "p. ej. de-frankfurt-1",
@@ -544,7 +793,7 @@
       "address": "Dirección",
       "address": "Dirección",
       "port": "Puerto",
       "port": "Puerto",
       "basePath": "Ruta base",
       "basePath": "Ruta base",
-      "apiToken": "Token de API",
+      "apiToken": "Token API",
       "apiTokenPlaceholder": "Token desde la página de Configuración del panel remoto",
       "apiTokenPlaceholder": "Token desde la página de Configuración del panel remoto",
       "apiTokenHint": "El panel remoto expone su token de API en Configuración → Token de API.",
       "apiTokenHint": "El panel remoto expone su token de API en Configuración → Token de API.",
       "regenerate": "Regenerar token",
       "regenerate": "Regenerar token",
@@ -571,7 +820,7 @@
       "deleteConfirmContent": "Esto detiene la monitorización del nodo. El panel remoto en sí no se ve afectado.",
       "deleteConfirmContent": "Esto detiene la monitorización del nodo. El panel remoto en sí no se ve afectado.",
       "statusValues": {
       "statusValues": {
         "online": "En línea",
         "online": "En línea",
-        "offline": "Desconectado",
+        "offline": "Sin conexión",
         "unknown": "Desconocido"
         "unknown": "Desconocido"
       },
       },
       "toasts": {
       "toasts": {
@@ -590,7 +839,7 @@
       "title": "Configuraciones",
       "title": "Configuraciones",
       "save": "Guardar",
       "save": "Guardar",
       "infoDesc": "Cada cambio realizado aquí debe ser guardado. Por favor, reinicie el panel para aplicar los cambios.",
       "infoDesc": "Cada cambio realizado aquí debe ser guardado. Por favor, reinicie el panel para aplicar los cambios.",
-      "restartPanel": "Reiniciar Panel",
+      "restartPanel": "Reiniciar panel",
       "restartPanelDesc": "¿Está seguro de que desea reiniciar el panel? Haga clic en Aceptar para reiniciar después de 3 segundos. Si no puede acceder al panel después de reiniciar, por favor, consulte la información de registro del panel en el servidor.",
       "restartPanelDesc": "¿Está seguro de que desea reiniciar el panel? Haga clic en Aceptar para reiniciar después de 3 segundos. Si no puede acceder al panel después de reiniciar, por favor, consulte la información de registro del panel en el servidor.",
       "restartPanelSuccess": "El panel se reinició correctamente",
       "restartPanelSuccess": "El panel se reinició correctamente",
       "actions": "Acciones",
       "actions": "Acciones",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "La ruta base por defecto \"/\" es conocida — cámbiela a una ruta aleatoria.",
       "warnDefaultBasePath": "La ruta base por defecto \"/\" es conocida — cámbiela a una ruta aleatoria.",
       "warnDefaultSubPath": "La ruta de suscripción por defecto \"/sub/\" es conocida — cámbiela.",
       "warnDefaultSubPath": "La ruta de suscripción por defecto \"/sub/\" es conocida — cámbiela.",
       "warnDefaultJsonPath": "La ruta de suscripción JSON por defecto \"/json/\" es conocida — cámbiela.",
       "warnDefaultJsonPath": "La ruta de suscripción JSON por defecto \"/json/\" es conocida — cámbiela.",
-      "TGBotSettings": "Configuraciones de Bot de Telegram",
+      "TGBotSettings": "Bot de Telegram",
       "panelListeningIP": "IP de Escucha del Panel",
       "panelListeningIP": "IP de Escucha del Panel",
       "panelListeningIPDesc": "Dejar en blanco por defecto para monitorear todas las IPs.",
       "panelListeningIPDesc": "Dejar en blanco por defecto para monitorear todas las IPs.",
       "panelListeningDomain": "Dominio de Escucha del Panel",
       "panelListeningDomain": "Dominio de Escucha del Panel",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Complete con una ruta absoluta que comience con.",
       "publicKeyPathDesc": "Complete con una ruta absoluta que comience con.",
       "privateKeyPath": "Ruta del Archivo de Clave Privada del Certificado del Panel",
       "privateKeyPath": "Ruta del Archivo de Clave Privada del Certificado del Panel",
       "privateKeyPathDesc": "Complete con una ruta absoluta que comience con.",
       "privateKeyPathDesc": "Complete con una ruta absoluta que comience con.",
-      "panelUrlPath": "Ruta Raíz de la URL del Panel",
+      "panelUrlPath": "Ruta URI",
       "panelUrlPathDesc": "Debe empezar con '/' y terminar con.",
       "panelUrlPathDesc": "Debe empezar con '/' y terminar con.",
       "pageSize": "Tamaño de paginación",
       "pageSize": "Tamaño de paginación",
       "pageSizeDesc": "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar",
       "pageSizeDesc": "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar",
+      "panelProxy": "Proxy de red del panel",
+      "panelProxyDesc": "Enruta las peticiones salientes del propio panel (actualizaciones de geo, comprobaciones de versión de Xray/panel, Telegram) a través de este proxy para sortear el filtrado de GitHub/Telegram en el servidor. Acepta socks5:// o http(s)://, p. ej. una entrada SOCKS local de Xray. Deja vacío para conexión directa.",
       "remarkModel": "Modelo de observación y carácter de separación",
       "remarkModel": "Modelo de observación y carácter de separación",
       "datepicker": "selector de fechas",
       "datepicker": "selector de fechas",
       "datepickerPlaceholder": "Seleccionar fecha",
       "datepickerPlaceholder": "Seleccionar fecha",
@@ -632,9 +883,9 @@
       "telegramBotEnableDesc": "Conéctese a las funciones de este panel a través del bot de Telegram.",
       "telegramBotEnableDesc": "Conéctese a las funciones de este panel a través del bot de Telegram.",
       "telegramToken": "Token de Telegram",
       "telegramToken": "Token de Telegram",
       "telegramTokenDesc": "Debe obtener el token del administrador de bots de Telegram {'@'}botfather.",
       "telegramTokenDesc": "Debe obtener el token del administrador de bots de Telegram {'@'}botfather.",
-      "telegramProxy": "Socks5 Proxy",
+      "telegramProxy": "Proxy SOCKS",
       "telegramProxyDesc": "Si necesita el proxy Socks5 para conectarse a Telegram. Ajuste su configuración según la guía.",
       "telegramProxyDesc": "Si necesita el proxy Socks5 para conectarse a Telegram. Ajuste su configuración según la guía.",
-      "telegramAPIServer": "API Server de Telegram",
+      "telegramAPIServer": "Servidor API de Telegram",
       "telegramAPIServerDesc": "El servidor API de Telegram a utilizar. Déjelo en blanco para utilizar el servidor predeterminado.",
       "telegramAPIServerDesc": "El servidor API de Telegram a utilizar. Déjelo en blanco para utilizar el servidor predeterminado.",
       "telegramChatId": "IDs de Chat de Telegram para Administradores",
       "telegramChatId": "IDs de Chat de Telegram para Administradores",
       "telegramChatIdDesc": "IDs de Chat múltiples separados por comas. Use {'@'}userinfobot o use el comando '/id' en el bot para obtener sus IDs de Chat.",
       "telegramChatIdDesc": "IDs de Chat múltiples separados por comas. Use {'@'}userinfobot o use el comando '/id' en el bot para obtener sus IDs de Chat.",
@@ -658,6 +909,8 @@
       "subEnable": "Habilitar Servicio",
       "subEnable": "Habilitar Servicio",
       "subEnableDesc": "Función de suscripción con configuración separada.",
       "subEnableDesc": "Función de suscripción con configuración separada.",
       "subJsonEnable": "Habilitar/Deshabilitar el endpoint de suscripción JSON de forma independiente.",
       "subJsonEnable": "Habilitar/Deshabilitar el endpoint de suscripción JSON de forma independiente.",
+      "subJsonEnableTitle": "Suscripción JSON",
+      "subClashEnableTitle": "Suscripción Clash / Mihomo",
       "subTitle": "Título de la Suscripción",
       "subTitle": "Título de la Suscripción",
       "subTitleDesc": "Título mostrado en el cliente VPN",
       "subTitleDesc": "Título mostrado en el cliente VPN",
       "subSupportUrl": "URL de soporte",
       "subSupportUrl": "URL de soporte",
@@ -678,13 +931,13 @@
       "subCertPathDesc": "Complete con una ruta absoluta que comience con '/'",
       "subCertPathDesc": "Complete con una ruta absoluta que comience con '/'",
       "subKeyPath": "Ruta del Archivo de Clave Privada del Certificado de Suscripción",
       "subKeyPath": "Ruta del Archivo de Clave Privada del Certificado de Suscripción",
       "subKeyPathDesc": "Complete con una ruta absoluta que comience con '/'",
       "subKeyPathDesc": "Complete con una ruta absoluta que comience con '/'",
-      "subPath": "Ruta Raíz de la URL de Suscripción",
+      "subPath": "Ruta URI",
       "subPathDesc": "Debe empezar con '/' y terminar con '/'",
       "subPathDesc": "Debe empezar con '/' y terminar con '/'",
       "subDomain": "Dominio de Escucha",
       "subDomain": "Dominio de Escucha",
       "subDomainDesc": "Dejar en blanco por defecto para monitorear todos los dominios e IPs.",
       "subDomainDesc": "Dejar en blanco por defecto para monitorear todos los dominios e IPs.",
       "subUpdates": "Intervalos de Actualización de Suscripción",
       "subUpdates": "Intervalos de Actualización de Suscripción",
       "subUpdatesDesc": "Horas de intervalo entre actualizaciones en la aplicación del cliente.",
       "subUpdatesDesc": "Horas de intervalo entre actualizaciones en la aplicación del cliente.",
-      "subEncrypt": "Encriptar configuraciones",
+      "subEncrypt": "Codificar",
       "subEncryptDesc": "Encriptar las configuraciones devueltas en la suscripción.",
       "subEncryptDesc": "Encriptar las configuraciones devueltas en la suscripción.",
       "subShowInfo": "Mostrar información de uso",
       "subShowInfo": "Mostrar información de uso",
       "subShowInfoDesc": "Mostrar tráfico restante y fecha después del nombre de configuración.",
       "subShowInfoDesc": "Mostrar tráfico restante y fecha después del nombre de configuración.",
@@ -693,7 +946,7 @@
       "subURI": "URI de proxy inverso",
       "subURI": "URI de proxy inverso",
       "subURIDesc": "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy",
       "subURIDesc": "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy",
       "externalTrafficInformEnable": "Informe de tráfico externo",
       "externalTrafficInformEnable": "Informe de tráfico externo",
-      "externalTrafficInformEnableDesc": "Informar a la API externa sobre cada actualización de tráfico.",
+      "externalTrafficInformEnableDesc": "Informar a una API externa en cada actualización de tráfico.",
       "externalTrafficInformURI": "URI de información de tráfico externo",
       "externalTrafficInformURI": "URI de información de tráfico externo",
       "externalTrafficInformURIDesc": "Las actualizaciones de tráfico se envían a este URI.",
       "externalTrafficInformURIDesc": "Las actualizaciones de tráfico se envían a este URI.",
       "restartXrayOnClientDisable": "Reiniciar Xray tras desactivación automática",
       "restartXrayOnClientDisable": "Reiniciar Xray tras desactivación automática",
@@ -703,6 +956,54 @@
       "fragmentSett": "Configuración de Fragmentación",
       "fragmentSett": "Configuración de Fragmentación",
       "noisesDesc": "Activar Sonidos",
       "noisesDesc": "Activar Sonidos",
       "noisesSett": "Configuración de Sonidos",
       "noisesSett": "Configuración de Sonidos",
+      "trustedProxyCidrs": "CIDR de proxy de confianza",
+      "trustedProxyCidrsDesc": "IP/CIDR separados por coma que pueden establecer las cabeceras de host, proto e IP del cliente reenviadas.",
+      "ldap": {
+        "enable": "Habilitar sincronización LDAP",
+        "host": "Host LDAP",
+        "port": "Puerto LDAP",
+        "useTls": "Usar TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Configurada; deja en blanco para mantener la contraseña actual.",
+        "passwordUnconfigured": "No configurada.",
+        "passwordPlaceholder": "Configurada — introduce un nuevo valor para reemplazar",
+        "baseDn": "Base DN",
+        "userFilter": "Filtro de usuario",
+        "userAttr": "Atributo de usuario (username/email)",
+        "vlessField": "Atributo flag VLESS",
+        "flagField": "Atributo flag genérico (opcional)",
+        "flagFieldDesc": "Si se establece, sobrescribe el flag VLESS — p. ej. shadowInactive.",
+        "truthyValues": "Valores truthy",
+        "truthyValuesDesc": "Separados por coma; por defecto: true,1,yes,on",
+        "invertFlag": "Invertir flag",
+        "invertFlagDesc": "Habilita cuando el atributo significa «deshabilitado» (p. ej. shadowInactive).",
+        "syncSchedule": "Programación de sincronización",
+        "syncScheduleDesc": "Cadena tipo cron, p. ej. @every 1m",
+        "inboundTags": "Etiquetas de entradas",
+        "inboundTagsDesc": "Entradas en las que la sincronización LDAP puede auto-crear o auto-eliminar clientes.",
+        "noInbounds": "No se encontraron entradas. Crea una en Entradas primero.",
+        "autoCreate": "Crear clientes automáticamente",
+        "autoDelete": "Eliminar clientes automáticamente",
+        "defaultTotalGb": "Total por defecto (GB)",
+        "defaultExpiryDays": "Caducidad por defecto (días)",
+        "defaultIpLimit": "Límite IP por defecto"
+      },
+      "subFormats": {
+        "packets": "Paquetes",
+        "length": "Longitud",
+        "interval": "Intervalo",
+        "maxSplit": "Máx. división",
+        "noises": "Ruidos",
+        "noiseItem": "Ruido №{n}",
+        "type": "Tipo",
+        "packet": "Paquete",
+        "delayMs": "Retraso (ms)",
+        "applyTo": "Aplicar a",
+        "addNoise": "+ Ruido",
+        "concurrency": "Concurrencia",
+        "xudpConcurrency": "Concurrencia xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido.",
       "muxDesc": "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido.",
       "muxSett": "Configuración Mux",
       "muxSett": "Configuración Mux",
@@ -758,6 +1059,9 @@
       "save": "Guardar configuración",
       "save": "Guardar configuración",
       "restart": "Reiniciar Xray",
       "restart": "Reiniciar Xray",
       "restartSuccess": "Xray se ha reiniciado correctamente",
       "restartSuccess": "Xray se ha reiniciado correctamente",
+      "restartOutputTitle": "Salida del reinicio de Xray",
+      "restartConfirmTitle": "¿Reiniciar xray?",
+      "restartConfirmContent": "Recarga el servicio xray con la configuración guardada.",
       "stopSuccess": "Xray se ha detenido correctamente",
       "stopSuccess": "Xray se ha detenido correctamente",
       "restartError": "Ocurrió un error al reiniciar Xray.",
       "restartError": "Ocurrió un error al reiniciar Xray.",
       "stopError": "Ocurrió un error al detener Xray.",
       "stopError": "Ocurrió un error al detener Xray.",
@@ -790,14 +1094,16 @@
       "outboundTestUrl": "URL de prueba de outbound",
       "outboundTestUrl": "URL de prueba de outbound",
       "outboundTestUrlDesc": "URL usada al probar la conectividad del outbound",
       "outboundTestUrlDesc": "URL usada al probar la conectividad del outbound",
       "Torrent": "Prohibir Uso de BitTorrent",
       "Torrent": "Prohibir Uso de BitTorrent",
-      "Inbounds": "Entrante",
+      "Inbounds": "Entradas",
       "InboundsDesc": "Cambia la plantilla de configuración para aceptar clientes específicos.",
       "InboundsDesc": "Cambia la plantilla de configuración para aceptar clientes específicos.",
       "Outbounds": "Salidas",
       "Outbounds": "Salidas",
       "Balancers": "Equilibradores",
       "Balancers": "Equilibradores",
+      "balancerTagRequired": "La etiqueta es obligatoria",
+      "balancerSelectorRequired": "Elige al menos una salida",
       "OutboundsDesc": "Cambia la plantilla de configuración para definir formas de salida para este servidor.",
       "OutboundsDesc": "Cambia la plantilla de configuración para definir formas de salida para este servidor.",
       "Routings": "Reglas de enrutamiento",
       "Routings": "Reglas de enrutamiento",
       "RoutingsDesc": "¡La prioridad de cada regla es importante!",
       "RoutingsDesc": "¡La prioridad de cada regla es importante!",
-      "completeTemplate": "Todos",
+      "completeTemplate": "Todo",
       "logLevel": "Nivel de registro",
       "logLevel": "Nivel de registro",
       "logLevelDesc": "El nivel de registro para registros de errores, que indica la información que debe registrarse.",
       "logLevelDesc": "El nivel de registro para registros de errores, que indica la información que debe registrarse.",
       "accessLog": "Registro de acceso",
       "accessLog": "Registro de acceso",
@@ -827,11 +1133,78 @@
         "inbound": "Entrante",
         "inbound": "Entrante",
         "outbound": "Saliente",
         "outbound": "Saliente",
         "balancer": "Equilibrador",
         "balancer": "Equilibrador",
-        "info": "Información",
+        "info": "Info",
         "add": "Agregar Regla",
         "add": "Agregar Regla",
         "edit": "Editar Regla",
         "edit": "Editar Regla",
         "useComma": "Elementos separados por comas"
         "useComma": "Elementos separados por comas"
       },
       },
+      "routing": {
+        "dragToReorder": "Arrastra para reordenar"
+      },
+      "ruleForm": {
+        "sourceIps": "IPs de origen",
+        "sourcePort": "Puerto de origen",
+        "vlessRoute": "Ruta VLESS",
+        "attributes": "Atributos",
+        "value": "Valor",
+        "user": "Usuario",
+        "inboundTags": "Etiquetas de entradas",
+        "outboundTag": "Etiqueta de salida",
+        "balancerTag": "Etiqueta de balanceador",
+        "balancerTagTooltip": "Enruta el tráfico a través de uno de los balanceadores configurados"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Etiqueta ya usada por otra salida",
+        "tagRequired": "La etiqueta es obligatoria",
+        "tagPlaceholder": "etiqueta-única",
+        "localIpPlaceholder": "IP local",
+        "addressRequired": "La dirección es obligatoria",
+        "portRequired": "El puerto es obligatorio",
+        "optional": "opcional",
+        "udpOverTcp": "UDP sobre TCP",
+        "uotVersion": "Versión UoT",
+        "inboundTag": "Etiqueta de entrada",
+        "inboundTagPlaceholder": "etiqueta de entrada usada en reglas de enrutamiento",
+        "responseType": "Tipo de respuesta",
+        "rewriteNetwork": "Reescribir red",
+        "unchanged": "(sin cambios)",
+        "unchangedAddress": "(sin cambios) p. ej. 1.1.1.1",
+        "rules": "Reglas",
+        "ruleN": "Regla {n}",
+        "action": "Acción",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Reglas finales",
+        "overrideXrayPrivateIp": "Sobrescribir el bloqueo de IP privada por defecto de Xray",
+        "blockDelay": "Retraso de bloqueo (ms)",
+        "reverseSniffing": "Sniffing inverso",
+        "workers": "Workers",
+        "reserved": "Reservado",
+        "minUploadInterval": "Intervalo mín. de subida (ms)",
+        "maxUploadSizeBytes": "Tamaño máx. de subida (bytes)",
+        "uplinkChunkSize": "Tamaño de chunk Uplink",
+        "noGrpcHeader": "Sin cabecera gRPC",
+        "maxConcurrency": "Máx. concurrencia",
+        "maxConnections": "Máx. conexiones",
+        "maxReuseTimes": "Máx. reutilizaciones",
+        "maxRequestTimes": "Máx. peticiones",
+        "maxReusableSecs": "Máx. segundos reutilizables",
+        "keepAlivePeriod": "Periodo keep alive",
+        "authPassword": "Contraseña de auth",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "nombre del servidor",
+        "verifyPeerName": "Verificar nombre del peer",
+        "pinnedSha256": "SHA256 pinned",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Intervalo keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Interfaz",
+        "ipv6Only": "Solo IPv6",
+        "acceptProxyProtocol": "Aceptar proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Agregar salida",
         "addOutbound": "Agregar salida",
         "addReverse": "Agregar reverso",
         "addReverse": "Agregar reverso",
@@ -846,8 +1219,8 @@
         "reverse": "Reverso",
         "reverse": "Reverso",
         "domain": "Dominio",
         "domain": "Dominio",
         "type": "Tipo",
         "type": "Tipo",
-        "bridge": "puente",
-        "portal": "portal",
+        "bridge": "Bridge",
+        "portal": "Portal",
         "link": "Enlace",
         "link": "Enlace",
         "intercon": "Interconexión",
         "intercon": "Interconexión",
         "settings": "Configuración",
         "settings": "Configuración",
@@ -860,6 +1233,8 @@
         "testSuccess": "Prueba exitosa",
         "testSuccess": "Prueba exitosa",
         "testFailed": "Prueba fallida",
         "testFailed": "Prueba fallida",
         "testError": "Error al probar la salida",
         "testError": "Error al probar la salida",
+        "testModeTooltip": "TCP: sonda rápida solo de dial. HTTP: petición completa a través de xray.",
+        "testAll": "Probar todo",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Token de acceso",
         "accessToken": "Token de acceso",
         "country": "País",
         "country": "País",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "Selectores",
         "balancerSelectors": "Selectores",
         "tag": "Etiqueta",
         "tag": "Etiqueta",
         "tagDesc": "etiqueta única",
         "tagDesc": "etiqueta única",
+        "tagDuplicate": "Etiqueta ya usada por otro balanceador",
+        "tagPlaceholder": "etiqueta única de balanceador",
+        "selector": "Selector",
+        "fallback": "Fallback",
+        "expected": "Esperado",
+        "expectedPlaceholder": "número óptimo de nodos",
+        "maxRtt": "Máx. RTT",
+        "tolerance": "Tolerancia",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "No es posible utilizar balancerTag y outboundTag al mismo tiempo. Si se utilizan al mismo tiempo, sólo funcionará outboundTag."
         "balancerDesc": "No es posible utilizar balancerTag y outboundTag al mismo tiempo. Si se utilizan al mismo tiempo, sólo funcionará outboundTag."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Nivel de Usuario",
         "userLevel": "Nivel de Usuario",
         "userLevelDesc": "Todas las conexiones realizadas a través de este entrada utilizarán este nivel de usuario. El valor predeterminado es 0"
         "userLevelDesc": "Todas las conexiones realizadas a través de este entrada utilizarán este nivel de usuario. El valor predeterminado es 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Clave privada",
+        "noServers": "No se encontraron servidores para el país seleccionado",
+        "noPublicKey": "El servidor seleccionado no anuncia una clave pública NordLynx.",
+        "outboundAdded": "Salida NordVPN añadida",
+        "outboundUpdated": "Salida NordVPN actualizada"
+      },
+      "warp": {
+        "licenseError": "No se pudo establecer la licencia WARP.",
+        "fetchFirst": "Obtén primero la configuración WARP.",
+        "createAccount": "Crear cuenta WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID del dispositivo",
+        "licenseKey": "Clave de licencia",
+        "privateKey": "Clave privada",
+        "deleteAccount": "Eliminar cuenta",
+        "settings": "Ajustes",
+        "licenseKeyLabel": "Clave de licencia WARP / WARP+",
+        "key": "Clave",
+        "keyPlaceholder": "clave WARP+ de 26 caracteres",
+        "accountInfo": "Información de cuenta",
+        "deviceName": "Nombre del dispositivo",
+        "deviceModel": "Modelo del dispositivo",
+        "deviceEnabled": "Dispositivo habilitado",
+        "accountType": "Tipo de cuenta",
+        "role": "Rol",
+        "warpPlusData": "Datos WARP+",
+        "quota": "Cuota",
+        "usage": "Uso",
+        "addOutbound": "Añadir salida"
+      },
       "dns": {
       "dns": {
         "enable": "Habilitar DNS",
         "enable": "Habilitar DNS",
         "enableDesc": "Habilitar servidor DNS incorporado",
         "enableDesc": "Habilitar servidor DNS incorporado",
@@ -961,7 +1378,7 @@
     "unknown": "Desconocido",
     "unknown": "Desconocido",
     "inbounds": "Entradas",
     "inbounds": "Entradas",
     "clients": "Clientes",
     "clients": "Clientes",
-    "offline": "🔴 Desconectado",
+    "offline": "🔴 Sin conexión",
     "online": "🟢 En línea",
     "online": "🟢 En línea",
     "commands": {
     "commands": {
       "unknown": "❗ Comando desconocido",
       "unknown": "❗ Comando desconocido",
@@ -992,7 +1409,7 @@
       "2faFailed": "Error de 2FA",
       "2faFailed": "Error de 2FA",
       "report": "🕰 Informes programados: {{ .RunTime }}\r\n",
       "report": "🕰 Informes programados: {{ .RunTime }}\r\n",
       "datetime": "⏰ Fecha y Hora: {{ .DateTime }}\r\n",
       "datetime": "⏰ Fecha y Hora: {{ .DateTime }}\r\n",
-      "hostname": "💻 Nombre del Host: {{ .Hostname }}\r\n",
+      "hostname": "💻 Host: {{ .Hostname }}\r\n",
       "version": "🚀 Versión de X-UI: {{ .Version }}\r\n",
       "version": "🚀 Versión de X-UI: {{ .Version }}\r\n",
       "xrayVersion": "📡 Versión de Xray: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Versión de Xray: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
@@ -1001,15 +1418,15 @@
       "ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
       "ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ Tiempo de actividad del servidor: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ Tiempo de actividad del servidor: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 Carga del servidor: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 Carga del servidor: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 Memoria del servidor: {{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 Conteo de TCP: {{ .Count }}\r\n",
-      "udpCount": "🔸 Conteo de UDP: {{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 Tráfico: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 Tráfico: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Estado de Xray: {{ .State }}\r\n",
+      "xrayStatus": "ℹ️ Estado: {{ .State }}\r\n",
       "username": "👤 Nombre de usuario: {{ .Username }}\r\n",
       "username": "👤 Nombre de usuario: {{ .Username }}\r\n",
       "reason": "❗️ Motivo: {{ .Reason }}\r\n",
       "reason": "❗️ Motivo: {{ .Reason }}\r\n",
       "time": "⏰ Hora: {{ .Time }}\r\n",
       "time": "⏰ Hora: {{ .Time }}\r\n",
-      "inbound": "📍 Inbound: {{ .Remark }}\r\n",
+      "inbound": "📍 Entrada: {{ .Remark }}\r\n",
       "port": "🔌 Puerto: {{ .Port }}\r\n",
       "port": "🔌 Puerto: {{ .Port }}\r\n",
       "expire": "📅 Fecha de Vencimiento: {{ .Time }}\r\n",
       "expire": "📅 Fecha de Vencimiento: {{ .Time }}\r\n",
       "expireIn": "📅 Vence en: {{ .Time }}\r\n",
       "expireIn": "📅 Vence en: {{ .Time }}\r\n",
@@ -1019,7 +1436,7 @@
       "lastOnline": "🔙 Última conexión: {{ .Time }}\r\n",
       "lastOnline": "🔙 Última conexión: {{ .Time }}\r\n",
       "email": "📧 Email: {{ .Email }}\r\n",
       "email": "📧 Email: {{ .Email }}\r\n",
       "upload": "🔼 Subida: ↑{{ .Upload }}\r\n",
       "upload": "🔼 Subida: ↑{{ .Upload }}\r\n",
-      "download": "🔽 Bajada: ↓{{ .Download }}\r\n",
+      "download": "🔽 Descarga: ↓{{ .Download }}\r\n",
       "total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 Usuario de Telegram: {{ .TelegramID }}\r\n",
       "TGUser": "👤 Usuario de Telegram: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 Agotado {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 Agotado {{ .Type }}:\r\n",
@@ -1077,7 +1494,7 @@
       "ipLimit": "🔢 Límite de IP",
       "ipLimit": "🔢 Límite de IP",
       "setTGUser": "👤 Establecer Usuario de Telegram",
       "setTGUser": "👤 Establecer Usuario de Telegram",
       "toggle": "🔘 Habilitar / Deshabilitar",
       "toggle": "🔘 Habilitar / Deshabilitar",
-      "custom": "🔢 Costumbre",
+      "custom": "🔢 Personalizado",
       "confirmNumber": "✅ Confirmar: {{ .Num }}",
       "confirmNumber": "✅ Confirmar: {{ .Num }}",
       "confirmNumberAdd": "✅ Confirmar agregando: {{ .Num }}",
       "confirmNumberAdd": "✅ Confirmar agregando: {{ .Num }}",
       "limitTraffic": "🚧 Límite de tráfico",
       "limitTraffic": "🚧 Límite de tráfico",
@@ -1089,9 +1506,9 @@
       "use_default": "🏷️ Usar por defecto",
       "use_default": "🏷️ Usar por defecto",
       "change_id": "⚙️🔑 ID",
       "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 Contraseña",
       "change_password": "⚙️🔑 Contraseña",
-      "change_email": "⚙️📧 Correo electrónico",
+      "change_email": "⚙️📧 Email",
       "change_comment": "⚙️💬 Comentario",
       "change_comment": "⚙️💬 Comentario",
-      "change_flow": "⚙️🚦 Flujo",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "Reiniciar todo el tráfico",
       "ResetAllTraffics": "Reiniciar todo el tráfico",
       "SortedTrafficUsageReport": "Informe de uso de tráfico ordenado"
       "SortedTrafficUsageReport": "Informe de uso de tráfico ordenado"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Elige un Inbound"
       "chooseInbound": "Elige un Inbound"
     }
     }
   }
   }
-}
+}

+ 458 - 88
web/translation/fa-IR.json

@@ -20,6 +20,10 @@
   "protocol": "پروتکل",
   "protocol": "پروتکل",
   "search": "جستجو",
   "search": "جستجو",
   "filter": "فیلتر",
   "filter": "فیلتر",
+  "all": "همه",
+  "from": "از",
+  "to": "تا",
+  "done": "انجام شد",
   "loading": "...در حال بارگذاری",
   "loading": "...در حال بارگذاری",
   "refresh": "تازه‌سازی",
   "refresh": "تازه‌سازی",
   "clear": "پاک کردن",
   "clear": "پاک کردن",
@@ -35,14 +39,14 @@
   "info": "اطلاعات بیشتر",
   "info": "اطلاعات بیشتر",
   "edit": "ویرایش",
   "edit": "ویرایش",
   "delete": "حذف",
   "delete": "حذف",
-  "reset": "ریست",
+  "reset": "بازنشانی",
   "noData": "داده‌ای وجود ندارد.",
   "noData": "داده‌ای وجود ندارد.",
   "copySuccess": "باموفقیت کپی‌شد",
   "copySuccess": "باموفقیت کپی‌شد",
   "sure": "مطمئن",
   "sure": "مطمئن",
   "encryption": "رمزگذاری",
   "encryption": "رمزگذاری",
   "useIPv4ForHost": "از IPv4 برای میزبان استفاده کنید",
   "useIPv4ForHost": "از IPv4 برای میزبان استفاده کنید",
   "transmission": "راه‌اتصال",
   "transmission": "راه‌اتصال",
-  "host": "آدرس",
+  "host": "میزبان",
   "path": "مسیر",
   "path": "مسیر",
   "camouflage": "مبهم‌سازی",
   "camouflage": "مبهم‌سازی",
   "status": "وضعیت",
   "status": "وضعیت",
@@ -100,9 +104,10 @@
     "dashboard": "نمای کلی",
     "dashboard": "نمای کلی",
     "inbounds": "ورودی‌ها",
     "inbounds": "ورودی‌ها",
     "clients": "کلاینت‌ها",
     "clients": "کلاینت‌ها",
+    "groups": "گروه‌ها",
     "nodes": "نودها",
     "nodes": "نودها",
     "settings": "تنظیمات پنل",
     "settings": "تنظیمات پنل",
-    "xray": "پیکربندی ایکس‌ری",
+    "xray": "پیکربندی Xray",
     "apiDocs": "مستندات API",
     "apiDocs": "مستندات API",
     "logout": "خروج",
     "logout": "خروج",
     "link": "مدیریت",
     "link": "مدیریت",
@@ -123,16 +128,16 @@
     },
     },
     "index": {
     "index": {
       "title": "نمای کلی",
       "title": "نمای کلی",
-      "cpu": "پردازنده",
+      "cpu": "CPU",
       "logicalProcessors": "پردازنده‌های منطقی",
       "logicalProcessors": "پردازنده‌های منطقی",
       "frequency": "فرکانس",
       "frequency": "فرکانس",
-      "swap": "سواپ",
+      "swap": "Swap",
       "storage": "ذخیره‌سازی",
       "storage": "ذخیره‌سازی",
-      "memory": "حافظه رم",
-      "threads": "رشته‌ها",
-      "xrayStatus": "ایکس‌ری",
+      "memory": "RAM",
+      "threads": "نخ‌ها",
+      "xrayStatus": "Xray",
       "stopXray": "توقف",
       "stopXray": "توقف",
-      "restartXray": "شروع‌مجدد",
+      "restartXray": "راه‌اندازی مجدد",
       "xraySwitch": "‌نسخه",
       "xraySwitch": "‌نسخه",
       "xrayUpdates": "به‌روزرسانی‌های Xray",
       "xrayUpdates": "به‌روزرسانی‌های Xray",
       "xraySwitchClick": "نسخه مورد نظر را انتخاب کنید",
       "xraySwitchClick": "نسخه مورد نظر را انتخاب کنید",
@@ -229,7 +234,7 @@
       "customGeoErrUpdateAllIncomplete": "به‌روزرسانی یک یا چند منبع geo سفارشی ناموفق بود",
       "customGeoErrUpdateAllIncomplete": "به‌روزرسانی یک یا چند منبع geo سفارشی ناموفق بود",
       "customGeoEmpty": "هنوز منبع geo سفارشی‌ای ثبت نشده — برای ایجاد روی «افزودن» کلیک کنید",
       "customGeoEmpty": "هنوز منبع geo سفارشی‌ای ثبت نشده — برای ایجاد روی «افزودن» کلیک کنید",
       "dontRefresh": "در حال نصب، لطفا صفحه را رفرش نکنید",
       "dontRefresh": "در حال نصب، لطفا صفحه را رفرش نکنید",
-      "logs": "گزارش‌ها",
+      "logs": "لاگ‌ها",
       "config": "پیکربندی",
       "config": "پیکربندی",
       "backup": "پشتیبان‌گیری",
       "backup": "پشتیبان‌گیری",
       "backupTitle": "پشتیبان‌گیری و بازیابی",
       "backupTitle": "پشتیبان‌گیری و بازیابی",
@@ -244,18 +249,18 @@
       "getConfigError": "خطا در دریافت فایل پیکربندی"
       "getConfigError": "خطا در دریافت فایل پیکربندی"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "کاربران",
+      "title": "ورودی‌ها",
       "totalDownUp": "دریافت/ارسال کل",
       "totalDownUp": "دریافت/ارسال کل",
       "totalUsage": "‌‌‌مصرف کل",
       "totalUsage": "‌‌‌مصرف کل",
       "inboundCount": "کل ورودی‌ها",
       "inboundCount": "کل ورودی‌ها",
-      "operate": "عملیات",
+      "operate": "منو",
       "enable": "فعال",
       "enable": "فعال",
       "remark": "نام",
       "remark": "نام",
       "node": "نود",
       "node": "نود",
       "deployTo": "استقرار روی",
       "deployTo": "استقرار روی",
       "localPanel": "پنل لوکال",
       "localPanel": "پنل لوکال",
       "fallbacks": {
       "fallbacks": {
-        "title": "فال‌بک‌ها",
+        "title": "Fallbackها",
         "help": "وقتی اتصالی روی این اینباند با هیچ کلاینتی تطبیق پیدا نمی‌کند، به یک اینباند دیگر ارجاع داده می‌شود. یک فرزند انتخاب کنید، فیلدهای مسیریابی (SNI / ALPN / Path / xver) خودکار از روی transport آن پر می‌شود — برای بیشتر تنظیمات نیازی به ویرایش نیست. هر فرزند باید روی 127.0.0.1 با security=none گوش بدهد.",
         "help": "وقتی اتصالی روی این اینباند با هیچ کلاینتی تطبیق پیدا نمی‌کند، به یک اینباند دیگر ارجاع داده می‌شود. یک فرزند انتخاب کنید، فیلدهای مسیریابی (SNI / ALPN / Path / xver) خودکار از روی transport آن پر می‌شود — برای بیشتر تنظیمات نیازی به ویرایش نیست. هر فرزند باید روی 127.0.0.1 با security=none گوش بدهد.",
         "empty": "هنوز فال‌بکی اضافه نشده",
         "empty": "هنوز فال‌بکی اضافه نشده",
         "add": "افزودن فال‌بک",
         "add": "افزودن فال‌بک",
@@ -273,14 +278,14 @@
       },
       },
       "protocol": "پروتکل",
       "protocol": "پروتکل",
       "port": "پورت",
       "port": "پورت",
-      "portMap": "پورت‌های نظیر",
+      "portMap": "نگاشت پورت",
       "traffic": "ترافیک",
       "traffic": "ترافیک",
       "details": "توضیحات",
       "details": "توضیحات",
-      "transportConfig": "نحوه اتصال",
+      "transportConfig": "انتقال",
       "expireDate": "مدت زمان",
       "expireDate": "مدت زمان",
       "createdAt": "ایجاد",
       "createdAt": "ایجاد",
       "updatedAt": "به‌روزرسانی",
       "updatedAt": "به‌روزرسانی",
-      "resetTraffic": "ریست ترافیک",
+      "resetTraffic": "بازنشانی ترافیک",
       "addInbound": "افزودن ورودی",
       "addInbound": "افزودن ورودی",
       "generalActions": "عملیات کلی",
       "generalActions": "عملیات کلی",
       "modifyInbound": "ویرایش ورودی",
       "modifyInbound": "ویرایش ورودی",
@@ -295,29 +300,29 @@
       "delAllClients": "حذف همه کلاینت‌ها",
       "delAllClients": "حذف همه کلاینت‌ها",
       "delAllClientsConfirmTitle": "حذف هر {count} کلاینت اینباند «{remark}»؟",
       "delAllClientsConfirmTitle": "حذف هر {count} کلاینت اینباند «{remark}»؟",
       "delAllClientsConfirmContent": "تمام کلاینت‌های این اینباند به همراه رکوردهای ترافیک‌شان حذف می‌شوند. خود اینباند باقی می‌ماند. این عمل غیرقابل بازگشت است.",
       "delAllClientsConfirmContent": "تمام کلاینت‌های این اینباند به همراه رکوردهای ترافیک‌شان حذف می‌شوند. خود اینباند باقی می‌ماند. این عمل غیرقابل بازگشت است.",
-      "attachClients": "اتصال کلاینت‌ها به…",
-      "addClientsToGroup": "افزودن کلاینت‌ها به گروه…",
-      "attachClientsTitle": "اتصال کلاینت‌های «{remark}»",
-      "attachClientsDesc": "همان {count} کلاینت (با همان UUID/پسورد و ترافیک مشترک) را به اینباند(های) انتخاب‌شده هم متصل می‌کند. روی این اینباند هم باقی می‌مانند.",
-      "attachClientsTargets": "اینباندهای مقصد",
-      "attachClientsNoTargets": "اینباند سازگار دیگری برای اتصال وجود ندارد.",
-      "attachClientsResult": "{attached} متصل شد، {skipped} رد شد.",
-      "attachClientsResultMixed": "{attached} متصل شد، {skipped} رد شد، {errors} خطا.",
-      "attachClientsSelectLabel": "کلاینت‌های قابل اتصال",
+      "attachClients": "الصاق کاربران به…",
+      "addClientsToGroup": "افزودن کاربران به گروه…",
+      "attachClientsTitle": "الصاق کاربران از «{remark}»",
+      "attachClientsDesc": "همان {count} کاربر (با UUID/رمز یکسان و ترافیک مشترک) را به ورودی‌(های) انتخابی الصاق می‌کند. در این ورودی هم باقی می‌مانند.",
+      "attachClientsTargets": "ورودی‌های مقصد",
+      "attachClientsNoTargets": "هیچ ورودی سازگار دیگری برای الصاق در دسترس نیست.",
+      "attachClientsResult": "الصاق شد {attached}، نادیده {skipped}.",
+      "attachClientsResultMixed": "الصاق شد {attached}، نادیده {skipped}، خطا {errors}.",
+      "attachClientsSelectLabel": "کاربران برای الصاق",
       "attachClientsSearchPlaceholder": "جستجوی ایمیل یا توضیح",
       "attachClientsSearchPlaceholder": "جستجوی ایمیل یا توضیح",
       "attachClientsStatusDisabled": "غیرفعال",
       "attachClientsStatusDisabled": "غیرفعال",
       "attachClientsSelectedCount": "{selected} از {total} انتخاب‌شده",
       "attachClientsSelectedCount": "{selected} از {total} انتخاب‌شده",
-      "detachClients": "جداسازی کلاینت‌ها",
-      "detachClientsTitle": "جداسازی کلاینت‌های «{remark}»",
-      "detachClientsDesc": "کلاینت‌های انتخاب‌شده فقط از همین اینباند جدا می‌شوند. خود رکورد کلاینت‌ها حفظ می‌شود (برای حذف کامل از Delete استفاده کنید). این اینباند مجموعاً {count} کلاینت دارد.",
-      "detachClientsResult": "{detached} جدا شد، {skipped} رد شد.",
-      "detachClientsResultMixed": "{detached} جدا شد، {skipped} رد شد، {errors} خطا.",
-      "detachClientsSelectLabel": "کلاینت‌های قابل جداسازی",
+      "detachClients": "جداسازی کاربران",
+      "detachClientsTitle": "جداسازی کاربران از «{remark}»",
+      "detachClientsDesc": "کاربر(های) انتخابی را تنها از این ورودی حذف می‌کند. خود رکورد کاربر حفظ می‌شود (برای حذف کامل از Delete استفاده کنید). مبدا در مجموع {count} کاربر دارد.",
+      "detachClientsResult": "جدا شد {detached}، نادیده {skipped}.",
+      "detachClientsResultMixed": "جدا شد {detached}، نادیده {skipped}، خطا {errors}.",
+      "detachClientsSelectLabel": "کاربران برای جداسازی",
       "exportLinksTitle": "خروجی لینک‌های اینباند",
       "exportLinksTitle": "خروجی لینک‌های اینباند",
       "exportSubsTitle": "خروجی لینک‌های ساب",
       "exportSubsTitle": "خروجی لینک‌های ساب",
       "exportAllLinksTitle": "خروجی لینک‌های همه اینباندها",
       "exportAllLinksTitle": "خروجی لینک‌های همه اینباندها",
       "exportAllSubsTitle": "خروجی لینک‌های ساب همه اینباندها",
       "exportAllSubsTitle": "خروجی لینک‌های ساب همه اینباندها",
-      "inboundJsonTitle": "JSON اینباند",
+      "inboundJsonTitle": "JSON ورودی",
       "deleteClient": "حذف کاربر",
       "deleteClient": "حذف کاربر",
       "deleteClientContent": "آیا مطمئن به حذف کاربر هستید؟",
       "deleteClientContent": "آیا مطمئن به حذف کاربر هستید؟",
       "resetTrafficContent": "آیا مطمئن به ریست ترافیک هستید؟",
       "resetTrafficContent": "آیا مطمئن به ریست ترافیک هستید؟",
@@ -327,7 +332,7 @@
       "destinationPort": "پورت مقصد",
       "destinationPort": "پورت مقصد",
       "targetAddress": "آدرس مقصد",
       "targetAddress": "آدرس مقصد",
       "monitorDesc": "به‌طور پیش‌فرض خالی‌بگذارید",
       "monitorDesc": "به‌طور پیش‌فرض خالی‌بگذارید",
-      "meansNoLimit": "0 = واحد: گیگابایت) نامحدود)",
+      "meansNoLimit": "= نامحدود. (واحد: GB)",
       "totalFlow": "ترافیک کل",
       "totalFlow": "ترافیک کل",
       "leaveBlankToNeverExpire": "برای منقضی‌نشدن خالی‌بگذارید",
       "leaveBlankToNeverExpire": "برای منقضی‌نشدن خالی‌بگذارید",
       "noRecommendKeepDefault": "توصیه‌می‌شود به‌طور پیش‌فرض حفظ‌شود",
       "noRecommendKeepDefault": "توصیه‌می‌شود به‌طور پیش‌فرض حفظ‌شود",
@@ -362,9 +367,10 @@
       "IPLimitlogDesc": "گزارش تاریخچه آی‌پی. برای فعال کردن ورودی پس از غیرفعال شدن، گزارش را پاک کنید",
       "IPLimitlogDesc": "گزارش تاریخچه آی‌پی. برای فعال کردن ورودی پس از غیرفعال شدن، گزارش را پاک کنید",
       "IPLimitlogclear": "پاک کردن گزارش‌ها",
       "IPLimitlogclear": "پاک کردن گزارش‌ها",
       "setDefaultCert": "استفاده از گواهی پنل",
       "setDefaultCert": "استفاده از گواهی پنل",
-      "streamTab": "استریم",
+      "setDefaultCertEmpty": "هیچ گواهی‌ای برای پنل پیکربندی نشده. ابتدا از تنظیمات یکی تعیین کنید.",
+      "streamTab": "Stream",
       "securityTab": "امنیت",
       "securityTab": "امنیت",
-      "sniffingTab": "اسنیفینگ",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "فقط متادیتا",
       "sniffingMetadataOnly": "فقط متادیتا",
       "sniffingRouteOnly": "فقط مسیریابی",
       "sniffingRouteOnly": "فقط مسیریابی",
       "sniffingIpsExcluded": "IPهای مستثنا",
       "sniffingIpsExcluded": "IPهای مستثنا",
@@ -382,15 +388,14 @@
         "allHelp": "شیء کامل اینباند با همه فیلدها در یک ویرایشگر.",
         "allHelp": "شیء کامل اینباند با همه فیلدها در یک ویرایشگر.",
         "settings": "تنظیمات",
         "settings": "تنظیمات",
         "settingsHelp": "ساختار بلوک settings در Xray:",
         "settingsHelp": "ساختار بلوک settings در Xray:",
-        "sniffing": "اسنیفینگ",
+        "sniffing": "Sniffing",
         "sniffingHelp": "ساختار بلوک sniffing در Xray:",
         "sniffingHelp": "ساختار بلوک sniffing در Xray:",
-        "stream": "استریم",
+        "stream": "Stream",
         "streamHelp": "ساختار بلوک stream در Xray:",
         "streamHelp": "ساختار بلوک stream در Xray:",
         "jsonErrorPrefix": "JSON پیشرفته"
         "jsonErrorPrefix": "JSON پیشرفته"
       },
       },
       "telegramDesc": "لطفا شناسه گفتگوی تلگرام را وارد کنید. (از دستور '/id' در ربات استفاده کنید) یا ({'@'}userinfobot)",
       "telegramDesc": "لطفا شناسه گفتگوی تلگرام را وارد کنید. (از دستور '/id' در ربات استفاده کنید) یا ({'@'}userinfobot)",
       "subscriptionDesc": "شما می‌توانید لینک سابسکربپشن خودرا در 'جزئیات' پیدا کنید، همچنین می‌توانید از همین نام برای چندین کاربر استفاده‌کنید",
       "subscriptionDesc": "شما می‌توانید لینک سابسکربپشن خودرا در 'جزئیات' پیدا کنید، همچنین می‌توانید از همین نام برای چندین کاربر استفاده‌کنید",
-      "info": "اطلاعات",
       "same": "همسان",
       "same": "همسان",
       "inboundData": "داده‌های ورودی",
       "inboundData": "داده‌های ورودی",
       "exportInbound": "استخراج ورودی",
       "exportInbound": "استخراج ورودی",
@@ -427,6 +432,139 @@
         "getNewmldsa65Error": "خطا در دریافت گواهی mldsa65.",
         "getNewmldsa65Error": "خطا در دریافت گواهی mldsa65.",
         "getNewVlessEncError": "خطا در دریافت گواهی VlessEnc."
         "getNewVlessEncError": "خطا در دریافت گواهی VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "بالا",
+        "moveDown": "پایین",
+        "addAll": "افزودن همه",
+        "addAllFallbackTooltip": "برای هر ورودی واجد شرایط که هنوز متصل نشده یک ردیف fallback اضافه می‌کند",
+        "peers": "Peers",
+        "addPeer": "افزودن peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "فقط ویندوز. CIDRها به‌صورت خودکار به جدول مسیریابی سیستم اضافه می‌شوند تا ترافیک مطابق از TUN عبور کند.",
+        "autoOutboundsInterface": "رابط خروجی خودکار",
+        "autoOutboundsInterfaceTooltip": "رابط فیزیکی برای ترافیک خروجی. از auto برای تشخیص استفاده کنید؛ زمانی که Auto system routes فعال باشد، به‌صورت خودکار فعال می‌شود.",
+        "rewriteAddress": "بازنویسی آدرس",
+        "rewritePort": "بازنویسی پورت",
+        "allowedNetwork": "شبکه مجاز",
+        "followRedirect": "دنبال‌کردن Redirect",
+        "accounts": "حساب‌ها",
+        "allowTransparent": "اجازه شفاف",
+        "encryptionMethod": "روش رمزنگاری",
+        "visionTestseed": "Vision testseed",
+        "version": "نسخه",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "استتار",
+        "type": "نوع",
+        "upstreamUrl": "آدرس Upstream",
+        "rewriteHost": "بازنویسی Host",
+        "skipTlsVerify": "رد تایید TLS",
+        "directory": "دایرکتوری",
+        "statusCode": "کد وضعیت",
+        "body": "Body",
+        "headers": "هدرها",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "نسخه درخواست",
+        "requestMethod": "متد درخواست",
+        "requestPath": "مسیر درخواست",
+        "requestHeaders": "هدرهای درخواست",
+        "responseVersion": "نسخه پاسخ",
+        "responseStatus": "وضعیت پاسخ",
+        "responseReason": "دلیل پاسخ",
+        "responseHeaders": "هدرهای پاسخ",
+        "heartbeatPeriod": "دوره Heartbeat",
+        "serviceName": "نام سرویس",
+        "authority": "Authority",
+        "multiMode": "حالت چندگانه",
+        "maxBufferedUpload": "حداکثر آپلود بافرشده",
+        "maxUploadSize": "حداکثر اندازه آپلود (بایت)",
+        "streamUpServer": "سرور Stream-Up",
+        "serverMaxHeaderBytes": "حداکثر بایت هدر سرور",
+        "paddingBytes": "بایت‌های Padding",
+        "uplinkHttpMethod": "متد HTTP آپلینک",
+        "paddingObfsMode": "حالت ابهام Padding",
+        "paddingKey": "کلید Padding",
+        "paddingHeader": "هدر Padding",
+        "paddingPlacement": "محل Padding",
+        "paddingMethod": "روش Padding",
+        "sessionPlacement": "محل نشست",
+        "sessionKey": "کلید نشست",
+        "sequencePlacement": "محل Sequence",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "محل داده Uplink",
+        "uplinkDataKey": "کلید داده Uplink",
+        "noSseHeader": "بدون هدر SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "آپلود (MB/s)",
+        "downlinkMbps": "دانلود (MB/s)",
+        "cwndMultiplier": "ضریب CWND",
+        "maxSendingWindow": "حداکثر پنجره ارسال",
+        "externalProxy": "پراکسی خارجی",
+        "sniPlaceholder": "SNI (پیش‌فرض همان host)",
+        "fingerprint": "اثرانگشت",
+        "defaultOption": "پیش‌فرض",
+        "routeMark": "علامت مسیر",
+        "tcpKeepAliveInterval": "بازه TCP Keep Alive",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "فقط IPv6",
+        "tcpCongestion": "تراکم TCP",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For مورد اعتماد",
+        "addressPortStrategy": "استراتژی آدرس+پورت",
+        "tryDelayMs": "تأخیر تلاش (ms)",
+        "prioritizeIPv6": "اولویت IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "حداکثر تلاش هم‌زمان",
+        "customSockopt": "Sockopt دلخواه",
+        "addCustomOption": "افزودن گزینه دلخواه",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "مجموعه‌های رمز",
+        "autoOption": "خودکار",
+        "minMaxVersion": "نسخه حداقل/حداکثر",
+        "rejectUnknownSni": "رد SNI ناشناخته",
+        "disableSystemRoot": "غیرفعال‌سازی System Root",
+        "sessionResumption": "ازسرگیری نشست",
+        "oneTimeLoading": "بارگذاری یک‌بار",
+        "usageOption": "گزینه استفاده",
+        "buildChain": "ساخت زنجیره",
+        "echKey": "کلید ECH",
+        "echConfig": "پیکربندی ECH",
+        "getNewEchCert": "دریافت گواهی ECH جدید",
+        "show": "نمایش",
+        "xver": "Xver",
+        "target": "هدف",
+        "maxTimeDiff": "حداکثر اختلاف زمان (ms)",
+        "minClientVer": "حداقل نسخه کلاینت",
+        "maxClientVer": "حداکثر نسخه کلاینت",
+        "shortIds": "Short IDها",
+        "spiderX": "SpiderX",
+        "getNewCert": "دریافت گواهی جدید",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "دریافت Seed جدید"
+      },
+      "info": {
+        "mode": "حالت",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "نام رابط",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "رابط خروجی",
+        "autoSystemRoutes": "مسیریابی خودکار سیستم",
+        "followRedirect": "FollowRedirect",
+        "auth": "احراز",
+        "noKernelTun": "TUN غیرکرنل",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "پیکربندی Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "درخواست",
           "request": "درخواست",
@@ -477,6 +615,20 @@
       "days": "روز",
       "days": "روز",
       "renew": "تمدید خودکار",
       "renew": "تمدید خودکار",
       "renewDesc": "تمدید خودکار پس از انقضا. (۰ = غیرفعال) (واحد: روز)",
       "renewDesc": "تمدید خودکار پس از انقضا. (۰ = غیرفعال) (واحد: روز)",
+      "searchPlaceholder": "جستجوی ایمیل، توضیح، Sub ID، UUID، رمز، احراز...",
+      "filterTitle": "فیلتر کاربران",
+      "clearAllFilters": "پاک کردن همه",
+      "sortOldest": "قدیمی‌ترین",
+      "sortNewest": "جدیدترین",
+      "sortRecentlyUpdated": "اخیراً به‌روزشده",
+      "sortRecentlyOnline": "اخیراً آنلاین",
+      "sortEmailAZ": "ایمیل ا→ی",
+      "sortEmailZA": "ایمیل ی→ا",
+      "sortMostTraffic": "بیشترین ترافیک",
+      "sortHighestRemaining": "بیشترین باقی‌مانده",
+      "sortExpiringSoonest": "نزدیک‌ترین انقضا",
+      "has": "دارد",
+      "hasNot": "ندارد",
       "title": "کلاینت‌ها",
       "title": "کلاینت‌ها",
       "actions": "عملیات",
       "actions": "عملیات",
       "totalGB": "مجموع ارسال/دریافت (گیگابایت)",
       "totalGB": "مجموع ارسال/دریافت (گیگابایت)",
@@ -487,6 +639,9 @@
       "subId": "شناسه اشتراک",
       "subId": "شناسه اشتراک",
       "online": "آنلاین",
       "online": "آنلاین",
       "email": "ایمیل",
       "email": "ایمیل",
+      "group": "گروه",
+      "groupDesc": "برچسبی منطقی برای دسته‌بندی کاربران مرتبط (مثل تیم، مشتری، منطقه). از نوار ابزار قابل فیلتر است.",
+      "groupPlaceholder": "مثلاً customer-a",
       "comment": "توضیحات",
       "comment": "توضیحات",
       "traffic": "ترافیک",
       "traffic": "ترافیک",
       "offline": "آفلاین",
       "offline": "آفلاین",
@@ -510,32 +665,45 @@
       "resetAllTraffics": "بازنشانی ترافیک همه کلاینت‌ها",
       "resetAllTraffics": "بازنشانی ترافیک همه کلاینت‌ها",
       "resetAllTrafficsTitle": "بازنشانی ترافیک همه کلاینت‌ها؟",
       "resetAllTrafficsTitle": "بازنشانی ترافیک همه کلاینت‌ها؟",
       "resetAllTrafficsContent": "شمارنده ارسال/دریافت همه کلاینت‌ها به صفر می‌رسد. سهمیه و تاریخ انقضا تغییری نمی‌کند. این عمل غیرقابل بازگشت است.",
       "resetAllTrafficsContent": "شمارنده ارسال/دریافت همه کلاینت‌ها به صفر می‌رسد. سهمیه و تاریخ انقضا تغییری نمی‌کند. این عمل غیرقابل بازگشت است.",
-      "empty": "هنوز کلاینتی نیست — برای شروع یکی اضافه کنید.",
       "deleteConfirmTitle": "حذف کلاینت {email}؟",
       "deleteConfirmTitle": "حذف کلاینت {email}؟",
       "deleteConfirmContent": "این کلاینت از تمام اینباندهای متصل حذف و سابقه ترافیک آن پاک می‌شود. این عمل غیرقابل بازگشت است.",
       "deleteConfirmContent": "این کلاینت از تمام اینباندهای متصل حذف و سابقه ترافیک آن پاک می‌شود. این عمل غیرقابل بازگشت است.",
       "deleteSelected": "حذف ({count})",
       "deleteSelected": "حذف ({count})",
       "adjustSelected": "تنظیم ({count})",
       "adjustSelected": "تنظیم ({count})",
-      "attach": "اتصال",
+      "subLinksSelected": "لینک‌های اشتراک ({count})",
+      "addToGroupTitle": "افزودن {count} کاربر به یک گروه",
+      "addToGroupTooltip": "یک گروه موجود را انتخاب کنید یا نام جدیدی تایپ کنید. برای حذف کاربران از گروه فعلی، از Ungroup استفاده کنید.",
+      "addToGroupPlaceholder": "نام گروه",
+      "addToGroupSuccessToast": "{count} کاربر به {group} اضافه شد",
+      "ungroupSuccessToast": "گروه از {count} کاربر پاک شد",
+      "ungroup": "خارج از گروه",
+      "ungroupConfirmTitle": "حذف {count} کاربر از گروهشان؟",
+      "ungroupConfirmContent": "برچسب گروه را روی هر کاربر انتخابی پاک می‌کند. کاربران حفظ می‌شوند (برای حذف کامل از Delete استفاده کنید).",
+      "addToGroup": "افزودن به گروه",
+      "attach": "الصاق",
       "adjust": "تنظیم",
       "adjust": "تنظیم",
-      "subLinks": "لینک‌های ساب",
+      "subLinks": "لینک‌های اشتراک",
       "selectedCount": "{count} انتخاب‌شده",
       "selectedCount": "{count} انتخاب‌شده",
-      "ungroup": "حذف گروه",
-      "ungroupConfirmTitle": "{count} کلاینت از گروهشان حذف شود؟",
-      "ungroupConfirmContent": "برچسب گروه از هر کلاینت انتخاب‌شده پاک می‌شود. خود کلاینت‌ها حفظ می‌شوند (برای حذف کامل، از Delete استفاده کنید).",
-      "addToGroup": "افزودن به گروه",
-      "attachSelected": "اتصال ({count})",
-      "attachToInboundsTitle": "اتصال {count} کلاینت به اینباند(ها)",
-      "attachToInboundsDesc": "{count} کلاینت انتخاب‌شده (با همان UUID/پسورد و ترافیک مشترک) به اینباند(های) انتخابی متصل می‌شوند. روی اینباندهای فعلی هم باقی می‌مانند.",
-      "attachToInboundsTargets": "اینباندهای مقصد",
-      "attachToInboundsNoTargets": "اینباند سازگار برای اتصال وجود ندارد.",
+      "attachSelected": "الصاق ({count})",
+      "attachToInboundsTitle": "الصاق {count} کاربر به ورودی‌(ها)",
+      "attachToInboundsDesc": "{count} کاربر انتخاب‌شده (همان UUID/رمز و ترافیک مشترک) را به ورودی‌های انتخابی الصاق می‌کند. الصاق‌های قبلی حفظ می‌شوند.",
+      "attachToInboundsTargets": "ورودی‌های مقصد",
+      "attachToInboundsNoTargets": "هیچ ورودی چندکاربره‌ای برای الصاق در دسترس نیست.",
       "detachSelected": "جداسازی ({count})",
       "detachSelected": "جداسازی ({count})",
       "detach": "جداسازی",
       "detach": "جداسازی",
-      "detachFromInboundsTitle": "جداسازی {count} کلاینت از اینباند(ها)",
-      "detachFromInboundsDesc": "{count} کلاینت انتخاب‌شده از اینباند(های) انتخابی جدا می‌شوند. زوج‌هایی که کلاینت در آن‌ها متصل نیست بی‌صدا رد می‌شوند. خود رکورد کلاینت‌ها حفظ می‌شود (برای حذف کامل از Delete استفاده کنید).",
-      "detachFromInboundsTargets": "اینباندهای مبدأ",
-      "detachFromInboundsNoTargets": "اینباند سازگار وجود ندارد.",
-      "detachFromInboundsResult": "{detached} جدا شد، {skipped} رد شد.",
-      "detachFromInboundsResultMixed": "{detached} جدا شد، {skipped} رد شد، {errors} خطا.",
+      "detachFromInboundsTitle": "جداسازی {count} کاربر از ورودی‌(ها)",
+      "detachFromInboundsDesc": "{count} کاربر انتخاب‌شده را از ورودی‌های انتخابی حذف می‌کند. در مواردی که کاربر الصاق نبوده، نادیده گرفته می‌شود. رکورد کاربر حفظ می‌شود (برای حذف کامل از Delete استفاده کنید).",
+      "detachFromInboundsTargets": "ورودی‌هایی برای جداسازی",
+      "detachFromInboundsNoTargets": "هیچ ورودی چندکاربره‌ای در دسترس نیست.",
+      "detachFromInboundsResult": "جدا شد {detached}، نادیده گرفته شد {skipped}.",
+      "detachFromInboundsResultMixed": "جدا شد {detached}، نادیده {skipped}، خطا {errors}.",
+      "subLinksTitle": "لینک‌های اشتراک ({count})",
+      "subLinkColumn": "آدرس اشتراک",
+      "subJsonLinkColumn": "آدرس JSON اشتراک",
+      "subLinksCopyAll": "کپی همه",
+      "subLinksCopiedAll": "{count} لینک کپی شد",
+      "subLinksEmpty": "هیچ‌کدام از کاربران انتخابی شناسه اشتراک ندارند.",
+      "subLinksDisabled": "سرویس اشتراک غیرفعال است.",
+      "subLinksDisabledHint": "برای ساخت لینک، اشتراک را در تنظیمات پنل ← اشتراک فعال کنید.",
       "bulkDeleteConfirmTitle": "حذف {count} کلاینت؟",
       "bulkDeleteConfirmTitle": "حذف {count} کلاینت؟",
       "bulkDeleteConfirmContent": "هر کلاینت انتخاب‌شده از تمام اینباندهای متصل حذف و سابقه ترافیک آن پاک می‌شود. این عمل غیرقابل بازگشت است.",
       "bulkDeleteConfirmContent": "هر کلاینت انتخاب‌شده از تمام اینباندهای متصل حذف و سابقه ترافیک آن پاک می‌شود. این عمل غیرقابل بازگشت است.",
       "bulkAdjustTitle": "تنظیم {count} کلاینت",
       "bulkAdjustTitle": "تنظیم {count} کلاینت",
@@ -546,12 +714,12 @@
       "delDepleted": "حذف اتمام‌یافته‌ها",
       "delDepleted": "حذف اتمام‌یافته‌ها",
       "delDepletedConfirmTitle": "حذف کلاینت‌های اتمام‌یافته؟",
       "delDepletedConfirmTitle": "حذف کلاینت‌های اتمام‌یافته؟",
       "delDepletedConfirmContent": "هر کلاینتی که سهمیه ترافیک‌اش تمام شده یا تاریخ انقضایش گذشته است حذف می‌شود. این عمل غیرقابل بازگشت است.",
       "delDepletedConfirmContent": "هر کلاینتی که سهمیه ترافیک‌اش تمام شده یا تاریخ انقضایش گذشته است حذف می‌شود. این عمل غیرقابل بازگشت است.",
-      "auth": "Auth",
-      "hysteriaAuth": "Auth (هیستریا)",
+      "auth": "احراز",
+      "hysteriaAuth": "احراز Hysteria",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
       "vmessSecurity": "امنیت VMess",
       "vmessSecurity": "امنیت VMess",
-      "reverseTag": "Reverse tag",
+      "reverseTag": "تگ معکوس",
       "reverseTagPlaceholder": "Reverse tag اختیاری",
       "reverseTagPlaceholder": "Reverse tag اختیاری",
       "telegramId": "شناسه کاربر تلگرام",
       "telegramId": "شناسه کاربر تلگرام",
       "telegramIdPlaceholder": "شناسه عددی کاربر تلگرام (۰ = هیچ)",
       "telegramIdPlaceholder": "شناسه عددی کاربر تلگرام (۰ = هیچ)",
@@ -571,6 +739,44 @@
         "delDepleted": "{count} کلاینت اتمام‌یافته حذف شد"
         "delDepleted": "{count} کلاینت اتمام‌یافته حذف شد"
       }
       }
     },
     },
+    "groups": {
+      "title": "گروه‌ها",
+      "name": "نام",
+      "clientCount": "کاربران در گروه",
+      "totalGroups": "تعداد گروه‌ها",
+      "totalGroupedClients": "کاربران دارای گروه",
+      "emptyGroups": "گروه‌های خالی",
+      "addGroup": "افزودن گروه",
+      "createSuccess": "گروه «{name}» ایجاد شد.",
+      "rename": "تغییر نام",
+      "renameTitle": "تغییر نام {name}",
+      "renameCollision": "گروهی به نام «{name}» از قبل وجود دارد.",
+      "renameSuccess": "گروه روی {count} کاربر تغییر نام داده شد.",
+      "deleteConfirmTitle": "حذف گروه {name}؟",
+      "deleteConfirmContent": "این عمل گروه را حذف می‌کند و برچسب آن را از {count} کاربر پاک می‌کند. خود کاربران حذف نمی‌شوند.",
+      "deleteSuccess": "گروه از {count} کاربر پاک شد.",
+      "resetTraffic": "بازنشانی ترافیک",
+      "resetConfirmTitle": "بازنشانی ترافیک گروه {name}؟",
+      "resetConfirmContent": "این عمل آپلود/دانلود تمام {count} کاربر این گروه را صفر می‌کند.",
+      "resetSuccess": "ترافیک {count} کاربر بازنشانی شد.",
+      "adjustSuccess": "{count} کاربر در {name} تنظیم شد.",
+      "emptyForAction": "این گروه هنوز کاربری ندارد.",
+      "deleteGroupOnly": "حذف گروه (نگه داشتن کاربران)",
+      "deleteClients": "حذف کاربران گروه",
+      "deleteClientsConfirmTitle": "حذف همه کاربران در {name}؟",
+      "deleteClientsConfirmContent": "این عمل {count} کاربر را به همراه رکورد ترافیک‌شان برای همیشه حذف می‌کند. برچسب گروه نیز پاک می‌شود. این عمل قابل بازگشت نیست.",
+      "deleteClientsSuccess": "{count} کاربر حذف شد.",
+      "deleteClientsMixed": "{ok} حذف شد، {failed} نادیده گرفته شد",
+      "addToGroup": "افزودن کاربران…",
+      "addToGroupTitle": "افزودن کاربران به گروه «{name}»",
+      "addToGroupDesc": "کاربرانی را برای افزودن به این گروه انتخاب کنید. الصاق‌های ورودی فعلی حفظ می‌شود؛ تنها برچسب گروه تغییر می‌کند. کاربرانی که از قبل در این گروه هستند نشان داده نمی‌شوند.",
+      "addToGroupEmpty": "کاربر دیگری برای افزودن در دسترس نیست.",
+      "addToGroupResult": "{count} کاربر به {name} اضافه شد.",
+      "removeFromGroup": "حذف کاربران…",
+      "removeFromGroupTitle": "حذف کاربران از گروه «{name}»",
+      "removeFromGroupDesc": "اعضایی را برای حذف از این گروه انتخاب کنید. خود کاربران حفظ می‌شوند (برای حذف کامل از «حذف کاربران گروه» استفاده کنید).",
+      "removeFromGroupResult": "{count} کاربر از {name} حذف شد."
+    },
     "nodes": {
     "nodes": {
       "title": "نودها",
       "title": "نودها",
       "addNode": "افزودن نود",
       "addNode": "افزودن نود",
@@ -596,9 +802,9 @@
       "allowPrivateAddressHint": "فقط برای نودهای روی شبکه خصوصی یا VPN فعال شود.",
       "allowPrivateAddressHint": "فقط برای نودهای روی شبکه خصوصی یا VPN فعال شود.",
       "enable": "فعال",
       "enable": "فعال",
       "status": "وضعیت",
       "status": "وضعیت",
-      "cpu": "پردازنده",
+      "cpu": "CPU",
       "mem": "حافظه",
       "mem": "حافظه",
-      "uptime": "زمان کارکرد",
+      "uptime": "مدت فعالیت",
       "latency": "تاخیر",
       "latency": "تاخیر",
       "lastHeartbeat": "آخرین ضربان",
       "lastHeartbeat": "آخرین ضربان",
       "xrayVersion": "نسخه Xray",
       "xrayVersion": "نسخه Xray",
@@ -633,7 +839,7 @@
       "title": "تنظیمات پنل",
       "title": "تنظیمات پنل",
       "save": "ذخیره",
       "save": "ذخیره",
       "infoDesc": "برای اعمال تغییرات در این بخش باید پس از ذخیره کردن، پنل را ریستارت کنید",
       "infoDesc": "برای اعمال تغییرات در این بخش باید پس از ذخیره کردن، پنل را ریستارت کنید",
-      "restartPanel": "ریستارت پنل",
+      "restartPanel": "راه‌اندازی مجدد پنل",
       "restartPanelDesc": "آیا مطمئن به ریستارت پنل هستید؟ اگر پس‌از ریستارت نمی‌توانید به پنل دسترسی پیدا کنید، لطفاً گزارش‌های موجود در اسکریپت پنل را بررسی کنید",
       "restartPanelDesc": "آیا مطمئن به ریستارت پنل هستید؟ اگر پس‌از ریستارت نمی‌توانید به پنل دسترسی پیدا کنید، لطفاً گزارش‌های موجود در اسکریپت پنل را بررسی کنید",
       "restartPanelSuccess": "پنل با موفقیت راه‌اندازی مجدد شد",
       "restartPanelSuccess": "پنل با موفقیت راه‌اندازی مجدد شد",
       "actions": "عملیات ها",
       "actions": "عملیات ها",
@@ -658,12 +864,12 @@
       "publicKeyPathDesc": "مسیر فایل کلیدعمومی برای وب پنل. با '/' شروع‌می‌شود",
       "publicKeyPathDesc": "مسیر فایل کلیدعمومی برای وب پنل. با '/' شروع‌می‌شود",
       "privateKeyPath": "مسیر کلید خصوصی",
       "privateKeyPath": "مسیر کلید خصوصی",
       "privateKeyPathDesc": "مسیر فایل کلیدخصوصی برای وب پنل. با '/' شروع‌می‌شود",
       "privateKeyPathDesc": "مسیر فایل کلیدخصوصی برای وب پنل. با '/' شروع‌می‌شود",
-      "panelUrlPath": "URI مسیر",
+      "panelUrlPath": "مسیر URI",
       "panelUrlPathDesc": "برای وب پنل. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد URI مسیر",
       "panelUrlPathDesc": "برای وب پنل. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد URI مسیر",
       "pageSize": "اندازه صفحه بندی جدول",
       "pageSize": "اندازه صفحه بندی جدول",
       "pageSizeDesc": "(اندازه صفحه برای جدول ورودی‌ها.(0 = غیرفعال",
       "pageSizeDesc": "(اندازه صفحه برای جدول ورودی‌ها.(0 = غیرفعال",
-      "panelProxy": "پراکسی شبکه‌ی پنل",
-      "panelProxyDesc": "درخواست‌های خروجیِ خودِ پنل (آپدیت geo، چک نسخه‌ی Xray و پنل، تلگرام) را از این پراکسی عبور می‌دهد تا فیلترینگ سروری گیت‌هاب/تلگرام دور زده شود. پشتیبانی از socks5:// و http(s)://، برای نمونه یک اینباند SOCKS لوکالِ Xray. برای اتصال مستقیم خالی بگذارید.",
+      "panelProxy": "پراکسی شبکه پنل",
+      "panelProxyDesc": "درخواست‌های خروجی خود پنل (به‌روزرسانی geo، بررسی نسخه Xray/پنل، تلگرام) را از این پراکسی عبور می‌دهد تا فیلترینگ GitHub/تلگرام در سرور دور زده شود. socks5:// یا http(s):// قابل قبول است، مثل ورودی SOCKS محلی Xray. برای اتصال مستقیم خالی بگذارید.",
       "remarkModel": "نام‌کانفیگ و جداکننده",
       "remarkModel": "نام‌کانفیگ و جداکننده",
       "datepicker": "نوع تقویم",
       "datepicker": "نوع تقویم",
       "datepickerPlaceholder": "انتخاب تاریخ",
       "datepickerPlaceholder": "انتخاب تاریخ",
@@ -677,7 +883,7 @@
       "telegramBotEnableDesc": "ربات تلگرام را فعال می‌کند",
       "telegramBotEnableDesc": "ربات تلگرام را فعال می‌کند",
       "telegramToken": "توکن تلگرام",
       "telegramToken": "توکن تلگرام",
       "telegramTokenDesc": "دریافت کنید {'@'}botfather توکن را می‌توانید از",
       "telegramTokenDesc": "دریافت کنید {'@'}botfather توکن را می‌توانید از",
-      "telegramProxy": "SOCKS پراکسی",
+      "telegramProxy": "پراکسی SOCKS",
       "telegramProxyDesc": "را برای اتصال به تلگرام فعال می کند SOCKS5 پراکسی",
       "telegramProxyDesc": "را برای اتصال به تلگرام فعال می کند SOCKS5 پراکسی",
       "telegramAPIServer": "سرور API تلگرام",
       "telegramAPIServer": "سرور API تلگرام",
       "telegramAPIServerDesc": "API سرور تلگرام برای اتصال را تغییر میدهد. برای استفاده از سرور پیش فرض خالی بگذارید",
       "telegramAPIServerDesc": "API سرور تلگرام برای اتصال را تغییر میدهد. برای استفاده از سرور پیش فرض خالی بگذارید",
@@ -703,6 +909,8 @@
       "subEnable": "فعال‌سازی سرویس سابسکریپشن",
       "subEnable": "فعال‌سازی سرویس سابسکریپشن",
       "subEnableDesc": "سرویس سابسکریپشن‌ را فعال‌می‌کند",
       "subEnableDesc": "سرویس سابسکریپشن‌ را فعال‌می‌کند",
       "subJsonEnable": "فعال/غیرفعال‌سازی مستقل نقطه دسترسی سابسکریپشن JSON.",
       "subJsonEnable": "فعال/غیرفعال‌سازی مستقل نقطه دسترسی سابسکریپشن JSON.",
+      "subJsonEnableTitle": "اشتراک JSON",
+      "subClashEnableTitle": "اشتراک Clash / Mihomo",
       "subTitle": "عنوان اشتراک",
       "subTitle": "عنوان اشتراک",
       "subTitleDesc": "عنوان نمایش داده شده در کلاینت VPN",
       "subTitleDesc": "عنوان نمایش داده شده در کلاینت VPN",
       "subSupportUrl": "آدرس پشتیبانی",
       "subSupportUrl": "آدرس پشتیبانی",
@@ -723,13 +931,13 @@
       "subCertPathDesc": "مسیر فایل کلیدعمومی برای سرویس سابیکریپشن. با '/' شروع‌می‌شود",
       "subCertPathDesc": "مسیر فایل کلیدعمومی برای سرویس سابیکریپشن. با '/' شروع‌می‌شود",
       "subKeyPath": "مسیر کلید خصوصی",
       "subKeyPath": "مسیر کلید خصوصی",
       "subKeyPathDesc": "مسیر فایل کلیدخصوصی برای سرویس سابسکریپشن. با '/' شروع‌می‌شود",
       "subKeyPathDesc": "مسیر فایل کلیدخصوصی برای سرویس سابسکریپشن. با '/' شروع‌می‌شود",
-      "subPath": "URI مسیر",
+      "subPath": "مسیر URI",
       "subPathDesc": "برای سرویس سابسکریپشن. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد URI مسیر",
       "subPathDesc": "برای سرویس سابسکریپشن. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد URI مسیر",
       "subDomain": "نام دامنه",
       "subDomain": "نام دامنه",
       "subDomainDesc": "آدرس دامنه برای سرویس سابسکریپشن. برای گوش دادن به تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید‌",
       "subDomainDesc": "آدرس دامنه برای سرویس سابسکریپشن. برای گوش دادن به تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید‌",
       "subUpdates": "فاصله بروزرسانی‌ سابسکریپشن",
       "subUpdates": "فاصله بروزرسانی‌ سابسکریپشن",
       "subUpdatesDesc": "(فاصله مابین بروزرسانی در برنامه‌های کاربری. (واحد: ساعت",
       "subUpdatesDesc": "(فاصله مابین بروزرسانی در برنامه‌های کاربری. (واحد: ساعت",
-      "subEncrypt": "کدگذاری",
+      "subEncrypt": "انکود",
       "subEncryptDesc": "کدگذاری خواهدشد Base64 محتوای برگشتی سرویس سابسکریپشن برپایه",
       "subEncryptDesc": "کدگذاری خواهدشد Base64 محتوای برگشتی سرویس سابسکریپشن برپایه",
       "subShowInfo": "نمایش اطلاعات مصرف",
       "subShowInfo": "نمایش اطلاعات مصرف",
       "subShowInfoDesc": "ترافیک و زمان باقی‌مانده را در برنامه‌های کاربری نمایش می‌دهد",
       "subShowInfoDesc": "ترافیک و زمان باقی‌مانده را در برنامه‌های کاربری نمایش می‌دهد",
@@ -738,7 +946,7 @@
       "subURI": "پروکسی معکوس URI مسیر",
       "subURI": "پروکسی معکوس URI مسیر",
       "subURIDesc": "سابسکریپشن را برای استفاده در پشت پراکسی‌ها تغییر می‌دهد URI مسیر",
       "subURIDesc": "سابسکریپشن را برای استفاده در پشت پراکسی‌ها تغییر می‌دهد URI مسیر",
       "externalTrafficInformEnable": "اطلاع رسانی خارجی مصرف ترافیک",
       "externalTrafficInformEnable": "اطلاع رسانی خارجی مصرف ترافیک",
-      "externalTrafficInformEnableDesc": "مصرف ترافیک به سرویس خارجی ارسال می شود",
+      "externalTrafficInformEnableDesc": "به API خارجی در هر به‌روزرسانی ترافیک اطلاع بده.",
       "externalTrafficInformURI": "لینک اطلاع رسانی خارجی مصرف ترافیک",
       "externalTrafficInformURI": "لینک اطلاع رسانی خارجی مصرف ترافیک",
       "externalTrafficInformURIDesc": "ترافیک های مصرفی به این لینک هم ارسال می شود",
       "externalTrafficInformURIDesc": "ترافیک های مصرفی به این لینک هم ارسال می شود",
       "restartXrayOnClientDisable": "ری‌استارت Xray بعد از غیرفعال‌سازی خودکار",
       "restartXrayOnClientDisable": "ری‌استارت Xray بعد از غیرفعال‌سازی خودکار",
@@ -748,7 +956,55 @@
       "fragmentSett": "تنظیمات فرگمنت",
       "fragmentSett": "تنظیمات فرگمنت",
       "noisesDesc": "فعال کردن Noises.",
       "noisesDesc": "فعال کردن Noises.",
       "noisesSett": "تنظیمات Noises",
       "noisesSett": "تنظیمات Noises",
-      "mux": "ماکس",
+      "trustedProxyCidrs": "CIDRهای پراکسی مورد اعتماد",
+      "trustedProxyCidrsDesc": "IPها/CIDRها (با کاما) که مجازند هدرهای host، proto و client IP فوروارد را تنظیم کنند.",
+      "ldap": {
+        "enable": "فعال‌سازی همگام‌سازی LDAP",
+        "host": "میزبان LDAP",
+        "port": "پورت LDAP",
+        "useTls": "استفاده از TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "تنظیم‌شده؛ برای حفظ رمز فعلی خالی بگذارید.",
+        "passwordUnconfigured": "تنظیم نشده.",
+        "passwordPlaceholder": "تنظیم‌شده – برای جایگزینی مقدار جدید وارد کنید",
+        "baseDn": "Base DN",
+        "userFilter": "فیلتر کاربر",
+        "userAttr": "صفت کاربر (username/email)",
+        "vlessField": "صفت پرچم VLESS",
+        "flagField": "صفت پرچم عمومی (اختیاری)",
+        "flagFieldDesc": "اگر تعیین شود، پرچم VLESS را override می‌کند — مثل shadowInactive.",
+        "truthyValues": "مقادیر صحیح",
+        "truthyValuesDesc": "با کاما جدا شده؛ پیش‌فرض: true,1,yes,on",
+        "invertFlag": "وارونگی پرچم",
+        "invertFlagDesc": "وقتی صفت به معنی «غیرفعال» است فعال کنید (مثل shadowInactive).",
+        "syncSchedule": "زمان‌بندی همگام‌سازی",
+        "syncScheduleDesc": "رشته شبیه cron، مثل @every 1m",
+        "inboundTags": "تگ‌های ورودی",
+        "inboundTagsDesc": "ورودی‌هایی که همگام‌سازی LDAP اجازه دارد روی آن‌ها کاربر بسازد یا حذف کند.",
+        "noInbounds": "هیچ ورودی یافت نشد. ابتدا از بخش ورودی‌ها یکی بسازید.",
+        "autoCreate": "ساخت خودکار کاربران",
+        "autoDelete": "حذف خودکار کاربران",
+        "defaultTotalGb": "حجم پیش‌فرض (GB)",
+        "defaultExpiryDays": "انقضای پیش‌فرض (روز)",
+        "defaultIpLimit": "محدودیت IP پیش‌فرض"
+      },
+      "subFormats": {
+        "packets": "بسته‌ها",
+        "length": "طول",
+        "interval": "بازه",
+        "maxSplit": "حداکثر تقسیم",
+        "noises": "نویزها",
+        "noiseItem": "نویز №{n}",
+        "type": "نوع",
+        "packet": "بسته",
+        "delayMs": "تأخیر (ms)",
+        "applyTo": "اعمال بر",
+        "addNoise": "+ نویز",
+        "concurrency": "هم‌زمانی",
+        "xudpConcurrency": "هم‌زمانی xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
+      "mux": "Mux",
       "muxDesc": "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند",
       "muxDesc": "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند",
       "muxSett": "تنظیمات ماکس",
       "muxSett": "تنظیمات ماکس",
       "direct": "اتصال مستقیم",
       "direct": "اتصال مستقیم",
@@ -801,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "پیکربندی ایکس‌ری",
       "title": "پیکربندی ایکس‌ری",
       "save": "ذخیره",
       "save": "ذخیره",
-      "restart": "ریستارت ایکس‌ری",
+      "restart": "راه‌اندازی مجدد Xray",
       "restartSuccess": "Xray با موفقیت راه‌اندازی مجدد شد",
       "restartSuccess": "Xray با موفقیت راه‌اندازی مجدد شد",
+      "restartOutputTitle": "خروجی راه‌اندازی مجدد Xray",
+      "restartConfirmTitle": "راه‌اندازی مجدد xray؟",
+      "restartConfirmContent": "سرویس xray با پیکربندی ذخیره‌شده دوباره بارگذاری می‌شود.",
       "stopSuccess": "Xray با موفقیت متوقف شد",
       "stopSuccess": "Xray با موفقیت متوقف شد",
       "restartError": "خطا در راه‌اندازی مجدد Xray.",
       "restartError": "خطا در راه‌اندازی مجدد Xray.",
       "stopError": "خطا در توقف Xray.",
       "stopError": "خطا در توقف Xray.",
@@ -810,7 +1069,7 @@
       "advancedTemplate": "پیشرفته",
       "advancedTemplate": "پیشرفته",
       "generalConfigs": "استراتژی‌ کلی",
       "generalConfigs": "استراتژی‌ کلی",
       "generalConfigsDesc": "این گزینه‌ها استراتژی کلی ترافیک را تعیین می‌کنند",
       "generalConfigsDesc": "این گزینه‌ها استراتژی کلی ترافیک را تعیین می‌کنند",
-      "logConfigs": "گزارش",
+      "logConfigs": "لاگ",
       "logConfigsDesc": "گزارش‌ها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید",
       "logConfigsDesc": "گزارش‌ها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید",
       "blockConfigsDesc": "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند",
       "blockConfigsDesc": "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند",
       "basicRouting": "مسیریابی پایه",
       "basicRouting": "مسیریابی پایه",
@@ -840,11 +1099,11 @@
       "Outbounds": "خروجی‌ها",
       "Outbounds": "خروجی‌ها",
       "Balancers": "بالانسرها",
       "Balancers": "بالانسرها",
       "balancerTagRequired": "تگ الزامی است",
       "balancerTagRequired": "تگ الزامی است",
-      "balancerSelectorRequired": "حداقل یک outbound انتخاب کنید",
+      "balancerSelectorRequired": "حداقل یک خروجی انتخاب کنید",
       "OutboundsDesc": "مسیر ترافیک خروجی را تنظیم کنید",
       "OutboundsDesc": "مسیر ترافیک خروجی را تنظیم کنید",
       "Routings": "قوانین مسیریابی",
       "Routings": "قوانین مسیریابی",
       "RoutingsDesc": "اولویت هر قانون مهم است",
       "RoutingsDesc": "اولویت هر قانون مهم است",
-      "completeTemplate": "کامل",
+      "completeTemplate": "همه",
       "logLevel": "سطح گزارش",
       "logLevel": "سطح گزارش",
       "logLevelDesc": "سطح گزارش برای گزارش های خطا، نشان دهنده اطلاعاتی است که باید ثبت شوند.",
       "logLevelDesc": "سطح گزارش برای گزارش های خطا، نشان دهنده اطلاعاتی است که باید ثبت شوند.",
       "accessLog": "مسیر گزارش",
       "accessLog": "مسیر گزارش",
@@ -879,6 +1138,73 @@
         "edit": "ویرایش قانون",
         "edit": "ویرایش قانون",
         "useComma": "موارد جدا شده با کاما"
         "useComma": "موارد جدا شده با کاما"
       },
       },
+      "routing": {
+        "dragToReorder": "برای تغییر ترتیب بکشید"
+      },
+      "ruleForm": {
+        "sourceIps": "IPهای مبدا",
+        "sourcePort": "پورت مبدا",
+        "vlessRoute": "مسیر VLESS",
+        "attributes": "صفت‌ها",
+        "value": "مقدار",
+        "user": "کاربر",
+        "inboundTags": "تگ‌های ورودی",
+        "outboundTag": "تگ خروجی",
+        "balancerTag": "تگ بالانسر",
+        "balancerTagTooltip": "ترافیک را از یکی از بالانسرهای پیکربندی‌شده عبور می‌دهد"
+      },
+      "outboundForm": {
+        "tagDuplicate": "این تگ توسط خروجی دیگری استفاده شده است",
+        "tagRequired": "تگ الزامی است",
+        "tagPlaceholder": "تگ-منحصربه‌فرد",
+        "localIpPlaceholder": "IP محلی",
+        "addressRequired": "آدرس الزامی است",
+        "portRequired": "پورت الزامی است",
+        "optional": "اختیاری",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "نسخه UoT",
+        "inboundTag": "تگ ورودی",
+        "inboundTagPlaceholder": "تگ ورودی استفاده‌شده در قوانین مسیریابی",
+        "responseType": "نوع پاسخ",
+        "rewriteNetwork": "بازنویسی شبکه",
+        "unchanged": "(بدون تغییر)",
+        "unchangedAddress": "(بدون تغییر) مثل 1.1.1.1",
+        "rules": "قوانین",
+        "ruleN": "قانون {n}",
+        "action": "عمل",
+        "redirect": "بازهدایت",
+        "fragment": "Fragment",
+        "finalRules": "قوانین نهایی",
+        "overrideXrayPrivateIp": "override بلاک پیش‌فرض IP خصوصی Xray",
+        "blockDelay": "تأخیر بلاک (ms)",
+        "reverseSniffing": "Sniffing معکوس",
+        "workers": "Workerها",
+        "reserved": "رزرو شده",
+        "minUploadInterval": "حداقل بازه آپلود (ms)",
+        "maxUploadSizeBytes": "حداکثر اندازه آپلود (بایت)",
+        "uplinkChunkSize": "اندازه قطعه آپلینک",
+        "noGrpcHeader": "بدون هدر gRPC",
+        "maxConcurrency": "حداکثر هم‌زمانی",
+        "maxConnections": "حداکثر اتصال‌ها",
+        "maxReuseTimes": "حداکثر استفاده مجدد",
+        "maxRequestTimes": "حداکثر تعداد درخواست",
+        "maxReusableSecs": "حداکثر ثانیه قابل استفاده مجدد",
+        "keepAlivePeriod": "دوره Keep alive",
+        "authPassword": "رمز احراز",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "نام سرور",
+        "verifyPeerName": "تایید نام Peer",
+        "pinnedSha256": "SHA256 پین‌شده",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "بازه Keep alive",
+        "markFwmark": "علامت (fwmark)",
+        "interface": "رابط",
+        "ipv6Only": "فقط IPv6",
+        "acceptProxyProtocol": "پذیرش Proxy Protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "افزودن خروجی",
         "addOutbound": "افزودن خروجی",
         "addReverse": "افزودن معکوس",
         "addReverse": "افزودن معکوس",
@@ -887,7 +1213,7 @@
         "reverseTag": "تگ معکوس",
         "reverseTag": "تگ معکوس",
         "reverseTagDesc": "تگ خروجی پروکسی معکوس ساده VLESS. برای غیرفعال کردن خالی بگذارید. در صورت تنظیم، اتصالات این کلاینت می‌توانند به عنوان تونل پروکسی معکوس استفاده شوند.",
         "reverseTagDesc": "تگ خروجی پروکسی معکوس ساده VLESS. برای غیرفعال کردن خالی بگذارید. در صورت تنظیم، اتصالات این کلاینت می‌توانند به عنوان تونل پروکسی معکوس استفاده شوند.",
         "reverseTagPlaceholder": "تگ خروجی (خالی = غیرفعال)",
         "reverseTagPlaceholder": "تگ خروجی (خالی = غیرفعال)",
-        "tag": "برچسب",
+        "tag": "تگ",
         "tagDesc": "برچسب یگانه",
         "tagDesc": "برچسب یگانه",
         "address": "آدرس",
         "address": "آدرس",
         "reverse": "معکوس",
         "reverse": "معکوس",
@@ -907,6 +1233,8 @@
         "testSuccess": "تست موفقیت‌آمیز",
         "testSuccess": "تست موفقیت‌آمیز",
         "testFailed": "تست ناموفق",
         "testFailed": "تست ناموفق",
         "testError": "خطا در تست خروجی",
         "testError": "خطا در تست خروجی",
+        "testModeTooltip": "TCP: فقط dial سریع. HTTP: درخواست کامل از طریق xray.",
+        "testAll": "تست همه",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "توکن دسترسی",
         "accessToken": "توکن دسترسی",
         "country": "کشور",
         "country": "کشور",
@@ -921,8 +1249,18 @@
         "editBalancer": "ویرایش بالانسر",
         "editBalancer": "ویرایش بالانسر",
         "balancerStrategy": "استراتژی",
         "balancerStrategy": "استراتژی",
         "balancerSelectors": "انتخاب‌گرها",
         "balancerSelectors": "انتخاب‌گرها",
-        "tag": "برچسب",
+        "tag": "تگ",
         "tagDesc": "برچسب یگانه",
         "tagDesc": "برچسب یگانه",
+        "tagDuplicate": "این تگ توسط بالانسر دیگری استفاده شده است",
+        "tagPlaceholder": "تگ منحصربه‌فرد بالانسر",
+        "selector": "انتخابگر",
+        "fallback": "Fallback",
+        "expected": "مورد انتظار",
+        "expectedPlaceholder": "تعداد نود بهینه",
+        "maxRtt": "حداکثر RTT",
+        "tolerance": "تحمل",
+        "baselines": "خطوط پایه",
+        "costs": "هزینه‌ها",
         "balancerDesc": "امکان استفاده همزمان balancerTag و outboundTag باهم وجود ندارد. درصورت استفاده همزمان فقط outboundTag عمل خواهد کرد."
         "balancerDesc": "امکان استفاده همزمان balancerTag و outboundTag باهم وجود ندارد. درصورت استفاده همزمان فقط outboundTag عمل خواهد کرد."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -939,6 +1277,38 @@
         "userLevel": "سطح کاربر",
         "userLevel": "سطح کاربر",
         "userLevelDesc": "تمام اتصالات انجام‌شده از طریق این ورودی از این سطح کاربری استفاده خواهند کرد. مقدار پیش‌فرض 0 است"
         "userLevelDesc": "تمام اتصالات انجام‌شده از طریق این ورودی از این سطح کاربری استفاده خواهند کرد. مقدار پیش‌فرض 0 است"
       },
       },
+      "nord": {
+        "accessToken": "توکن دسترسی",
+        "privateKey": "کلید خصوصی",
+        "noServers": "سروری برای کشور انتخابی پیدا نشد",
+        "noPublicKey": "سرور انتخابی کلید عمومی NordLynx اعلام نمی‌کند.",
+        "outboundAdded": "خروجی NordVPN اضافه شد",
+        "outboundUpdated": "خروجی NordVPN به‌روزرسانی شد"
+      },
+      "warp": {
+        "licenseError": "تنظیم لایسنس WARP ناموفق بود.",
+        "fetchFirst": "ابتدا پیکربندی WARP را دریافت کنید.",
+        "createAccount": "ایجاد حساب WARP",
+        "accessToken": "توکن دسترسی",
+        "deviceId": "شناسه دستگاه",
+        "licenseKey": "کلید لایسنس",
+        "privateKey": "کلید خصوصی",
+        "deleteAccount": "حذف حساب",
+        "settings": "تنظیمات",
+        "licenseKeyLabel": "کلید لایسنس WARP / WARP+",
+        "key": "کلید",
+        "keyPlaceholder": "کلید ۲۶ کاراکتری WARP+",
+        "accountInfo": "اطلاعات حساب",
+        "deviceName": "نام دستگاه",
+        "deviceModel": "مدل دستگاه",
+        "deviceEnabled": "دستگاه فعال",
+        "accountType": "نوع حساب",
+        "role": "نقش",
+        "warpPlusData": "داده WARP+",
+        "quota": "سهمیه",
+        "usage": "مصرف",
+        "addOutbound": "افزودن خروجی"
+      },
       "dns": {
       "dns": {
         "enable": "فعال کردن حل دامنه",
         "enable": "فعال کردن حل دامنه",
         "enableDesc": "سرور حل دامنه داخلی را فعال کنید",
         "enableDesc": "سرور حل دامنه داخلی را فعال کنید",
@@ -1006,7 +1376,7 @@
     "hours": "ساعت",
     "hours": "ساعت",
     "minutes": "دقیقه",
     "minutes": "دقیقه",
     "unknown": "نامشخص",
     "unknown": "نامشخص",
-    "inbounds": "ورودی ها",
+    "inbounds": "ورودیها",
     "clients": "کاربران",
     "clients": "کاربران",
     "offline": "🔴 آفلاین",
     "offline": "🔴 آفلاین",
     "online": "🟢 آنلاین",
     "online": "🟢 آنلاین",
@@ -1039,24 +1409,24 @@
       "2faFailed": "خطای 2FA",
       "2faFailed": "خطای 2FA",
       "report": "🕰 گزارشات‌زمان‌بندی‌شده: {{ .RunTime }}\r\n",
       "report": "🕰 گزارشات‌زمان‌بندی‌شده: {{ .RunTime }}\r\n",
       "datetime": "⏰ تاریخ‌وزمان: {{ .DateTime }}\r\n",
       "datetime": "⏰ تاریخ‌وزمان: {{ .DateTime }}\r\n",
-      "hostname": "💻 نام‌میزبان: {{ .Hostname }}\r\n",
+      "hostname": "💻 میزبان: {{ .Hostname }}\r\n",
       "version": "🚀 نسخه‌پنل: {{ .Version }}\r\n",
       "version": "🚀 نسخه‌پنل: {{ .Version }}\r\n",
       "xrayVersion": "📡 نسخه‌هسته: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 نسخه‌هسته: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
-      "ip": "🌐 آدرس‌آی‌پی: {{ .IP }}\r\n",
-      "ips": "🔢 آدرس‌های آی‌پی:\r\n{{ .IPs }}\r\n",
+      "ip": "🌐 IP: {{ .IP }}\r\n",
+      "ips": "🔢 IPها:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ مدت‌کارکردسیستم: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ مدت‌کارکردسیستم: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 بارسیستم: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 بارسیستم: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
       "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
       "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
       "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
       "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 ترافیک: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 ترافیک: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ وضعیت‌ایکس‌ری: {{ .State }}\r\n",
+      "xrayStatus": "ℹ️ وضعیت: {{ .State }}\r\n",
       "username": "👤 نام‌کاربری: {{ .Username }}\r\n",
       "username": "👤 نام‌کاربری: {{ .Username }}\r\n",
       "reason": "❗️ دلیل: {{ .Reason }}\r\n",
       "reason": "❗️ دلیل: {{ .Reason }}\r\n",
       "time": "⏰ زمان: {{ .Time }}\r\n",
       "time": "⏰ زمان: {{ .Time }}\r\n",
-      "inbound": "📍 نام‌ورودی: {{ .Remark }}\r\n",
+      "inbound": "📍 ورودی: {{ .Remark }}\r\n",
       "port": "🔌 پورت: {{ .Port }}\r\n",
       "port": "🔌 پورت: {{ .Port }}\r\n",
       "expire": "📅 تاریخ‌انقضا: {{ .Time }}\r\n\r\n",
       "expire": "📅 تاریخ‌انقضا: {{ .Time }}\r\n\r\n",
       "expireIn": "📅 باقی‌ مانده‌ تا انقضا: {{ .Time }}\r\n\r\n",
       "expireIn": "📅 باقی‌ مانده‌ تا انقضا: {{ .Time }}\r\n\r\n",
@@ -1065,9 +1435,9 @@
       "online": "🌐 وضعیت اتصال: {{ .Status }}\r\n",
       "online": "🌐 وضعیت اتصال: {{ .Status }}\r\n",
       "lastOnline": "🔙 آخرین فعالیت: {{ .Time }}\r\n",
       "lastOnline": "🔙 آخرین فعالیت: {{ .Time }}\r\n",
       "email": "📧 ایمیل: {{ .Email }}\r\n",
       "email": "📧 ایمیل: {{ .Email }}\r\n",
-      "upload": "🔼 آپلود: {{ .Upload }}\r\n",
-      "download": "🔽 دانلود: {{ .Download }}\r\n",
-      "total": "🔄 کل: {{ .UpDown }} / {{ .Total }}\r\n",
+      "upload": "🔼 آپلود: {{ .Upload }}\r\n",
+      "download": "🔽 دانلود: {{ .Download }}\r\n",
+      "total": "📊 کل: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 کاربر تلگرام: {{ .TelegramID }}\r\n",
       "TGUser": "👤 کاربر تلگرام: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 {{ .Type }} به‌اتمام‌رسیده‌است:\r\n",
       "exhaustedMsg": "🚨 {{ .Type }} به‌اتمام‌رسیده‌است:\r\n",
       "exhaustedCount": "🚨 تعداد {{ .Type }} به‌اتمام‌رسیده‌است:\r\n",
       "exhaustedCount": "🚨 تعداد {{ .Type }} به‌اتمام‌رسیده‌است:\r\n",
@@ -1134,11 +1504,11 @@
       "submitDisable": "ارسال به عنوان غیرفعال ☑️",
       "submitDisable": "ارسال به عنوان غیرفعال ☑️",
       "submitEnable": "ارسال به عنوان فعال ✅",
       "submitEnable": "ارسال به عنوان فعال ✅",
       "use_default": "🏷️ استفاده از پیش‌فرض",
       "use_default": "🏷️ استفاده از پیش‌فرض",
-      "change_id": "⚙️🔑 شناسه",
+      "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 گذرواژه",
       "change_password": "⚙️🔑 گذرواژه",
       "change_email": "⚙️📧 ایمیل",
       "change_email": "⚙️📧 ایمیل",
       "change_comment": "⚙️💬 نظر",
       "change_comment": "⚙️💬 نظر",
-      "change_flow": "⚙️🚦 جریان",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "بازنشانی همه ترافیک‌ها",
       "ResetAllTraffics": "بازنشانی همه ترافیک‌ها",
       "SortedTrafficUsageReport": "گزارش استفاده از ترافیک مرتب‌شده"
       "SortedTrafficUsageReport": "گزارش استفاده از ترافیک مرتب‌شده"
     },
     },
@@ -1166,4 +1536,4 @@
       "chooseInbound": "یک ورودی انتخاب کنید"
       "chooseInbound": "یک ورودی انتخاب کنید"
     }
     }
   }
   }
-}
+}

+ 448 - 31
web/translation/id-ID.json

@@ -8,15 +8,22 @@
   "save": "Simpan",
   "save": "Simpan",
   "logout": "Keluar",
   "logout": "Keluar",
   "create": "Buat",
   "create": "Buat",
+  "add": "Tambah",
+  "remove": "Hapus",
   "update": "Perbarui",
   "update": "Perbarui",
   "copy": "Salin",
   "copy": "Salin",
   "copied": "Tersalin",
   "copied": "Tersalin",
+  "more": "lainnya",
   "download": "Unduh",
   "download": "Unduh",
   "remark": "Catatan",
   "remark": "Catatan",
   "enable": "Aktifkan",
   "enable": "Aktifkan",
   "protocol": "Protokol",
   "protocol": "Protokol",
   "search": "Cari",
   "search": "Cari",
   "filter": "Filter",
   "filter": "Filter",
+  "all": "Semua",
+  "from": "Dari",
+  "to": "Ke",
+  "done": "Selesai",
   "loading": "Memuat...",
   "loading": "Memuat...",
   "refresh": "Segarkan",
   "refresh": "Segarkan",
   "clear": "Bersihkan",
   "clear": "Bersihkan",
@@ -27,7 +34,7 @@
   "check": "Centang",
   "check": "Centang",
   "indefinite": "Tak Terbatas",
   "indefinite": "Tak Terbatas",
   "unlimited": "Tanpa Batas",
   "unlimited": "Tanpa Batas",
-  "none": "None",
+  "none": "Tidak ada",
   "qrCode": "Kode QR",
   "qrCode": "Kode QR",
   "info": "Informasi Lebih Lanjut",
   "info": "Informasi Lebih Lanjut",
   "edit": "Edit",
   "edit": "Edit",
@@ -40,8 +47,8 @@
   "useIPv4ForHost": "Gunakan IPv4 untuk host",
   "useIPv4ForHost": "Gunakan IPv4 untuk host",
   "transmission": "Transmisi",
   "transmission": "Transmisi",
   "host": "Host",
   "host": "Host",
-  "path": "Jalur",
-  "camouflage": "Obfuscation",
+  "path": "Path",
+  "camouflage": "Obfuskasi",
   "status": "Status",
   "status": "Status",
   "enabled": "Aktif",
   "enabled": "Aktif",
   "disabled": "Nonaktif",
   "disabled": "Nonaktif",
@@ -95,8 +102,9 @@
     "dark": "Gelap",
     "dark": "Gelap",
     "ultraDark": "Sangat Gelap",
     "ultraDark": "Sangat Gelap",
     "dashboard": "Ikhtisar",
     "dashboard": "Ikhtisar",
-    "inbounds": "Masuk",
+    "inbounds": "Inbound",
     "clients": "Klien",
     "clients": "Klien",
+    "groups": "Grup",
     "nodes": "Node",
     "nodes": "Node",
     "settings": "Pengaturan Panel",
     "settings": "Pengaturan Panel",
     "xray": "Konfigurasi Xray",
     "xray": "Konfigurasi Xray",
@@ -128,8 +136,8 @@
       "memory": "RAM",
       "memory": "RAM",
       "threads": "Thread",
       "threads": "Thread",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
-      "stopXray": "Stop",
-      "restartXray": "Restart",
+      "stopXray": "Hentikan",
+      "restartXray": "Mulai ulang",
       "xraySwitch": "Versi",
       "xraySwitch": "Versi",
       "xrayUpdates": "Pembaruan Xray",
       "xrayUpdates": "Pembaruan Xray",
       "xraySwitchClick": "Pilih versi yang ingin Anda pindah.",
       "xraySwitchClick": "Pilih versi yang ingin Anda pindah.",
@@ -143,7 +151,7 @@
       "xrayStatusUnknown": "Tidak diketahui",
       "xrayStatusUnknown": "Tidak diketahui",
       "xrayStatusRunning": "Berjalan",
       "xrayStatusRunning": "Berjalan",
       "xrayStatusStop": "Berhenti",
       "xrayStatusStop": "Berhenti",
-      "xrayStatusError": "Kesalahan",
+      "xrayStatusError": "Error",
       "xrayErrorPopoverTitle": "Terjadi kesalahan saat menjalankan Xray",
       "xrayErrorPopoverTitle": "Terjadi kesalahan saat menjalankan Xray",
       "operationHours": "Waktu Aktif",
       "operationHours": "Waktu Aktif",
       "systemHistoryTitle": "Riwayat Sistem",
       "systemHistoryTitle": "Riwayat Sistem",
@@ -241,7 +249,7 @@
       "getConfigError": "Terjadi kesalahan saat mengambil file konfigurasi"
       "getConfigError": "Terjadi kesalahan saat mengambil file konfigurasi"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "Masuk",
+      "title": "Inbound",
       "totalDownUp": "Total Terkirim/Diterima",
       "totalDownUp": "Total Terkirim/Diterima",
       "totalUsage": "Penggunaan Total",
       "totalUsage": "Penggunaan Total",
       "inboundCount": "Total Masuk",
       "inboundCount": "Total Masuk",
@@ -270,14 +278,14 @@
       },
       },
       "protocol": "Protokol",
       "protocol": "Protokol",
       "port": "Port",
       "port": "Port",
-      "portMap": "Port Mapping",
-      "traffic": "Traffic",
+      "portMap": "Pemetaan port",
+      "traffic": "Trafik",
       "details": "Rincian",
       "details": "Rincian",
       "transportConfig": "Transport",
       "transportConfig": "Transport",
       "expireDate": "Durasi",
       "expireDate": "Durasi",
       "createdAt": "Dibuat",
       "createdAt": "Dibuat",
       "updatedAt": "Diperbarui",
       "updatedAt": "Diperbarui",
-      "resetTraffic": "Reset Traffic",
+      "resetTraffic": "Reset trafik",
       "addInbound": "Tambahkan Masuk",
       "addInbound": "Tambahkan Masuk",
       "generalActions": "Tindakan Umum",
       "generalActions": "Tindakan Umum",
       "modifyInbound": "Ubah Masuk",
       "modifyInbound": "Ubah Masuk",
@@ -292,6 +300,24 @@
       "delAllClients": "Hapus Semua Klien",
       "delAllClients": "Hapus Semua Klien",
       "delAllClientsConfirmTitle": "Hapus semua {count} klien dari \"{remark}\"?",
       "delAllClientsConfirmTitle": "Hapus semua {count} klien dari \"{remark}\"?",
       "delAllClientsConfirmContent": "Menghapus setiap klien dari inbound ini dan menghapus catatan trafiknya. Inbound itu sendiri dipertahankan. Tindakan ini tidak dapat dibatalkan.",
       "delAllClientsConfirmContent": "Menghapus setiap klien dari inbound ini dan menghapus catatan trafiknya. Inbound itu sendiri dipertahankan. Tindakan ini tidak dapat dibatalkan.",
+      "attachClients": "Lampirkan klien ke…",
+      "addClientsToGroup": "Tambah klien ke grup…",
+      "attachClientsTitle": "Lampirkan klien dari «{remark}»",
+      "attachClientsDesc": "Melampirkan {count} klien yang sama (UUID/kata sandi sama dan trafik bersama) ke inbound terpilih. Tetap ada di inbound ini juga.",
+      "attachClientsTargets": "Inbound tujuan",
+      "attachClientsNoTargets": "Tidak ada inbound kompatibel lain untuk dilampirkan.",
+      "attachClientsResult": "Dilampirkan {attached}, dilewati {skipped}.",
+      "attachClientsResultMixed": "Dilampirkan {attached}, dilewati {skipped}, error {errors}.",
+      "attachClientsSelectLabel": "Klien untuk dilampirkan",
+      "attachClientsSearchPlaceholder": "Cari email atau komentar",
+      "attachClientsStatusDisabled": "Dinonaktifkan",
+      "attachClientsSelectedCount": "{selected} dari {total} dipilih",
+      "detachClients": "Lepas klien",
+      "detachClientsTitle": "Lepas klien dari «{remark}»",
+      "detachClientsDesc": "Menghapus klien terpilih hanya dari inbound ini. Catatan klien tetap dipertahankan (gunakan Delete untuk menghapus sepenuhnya). Sumber memiliki total {count} klien.",
+      "detachClientsResult": "Dilepas {detached}, dilewati {skipped}.",
+      "detachClientsResultMixed": "Dilepas {detached}, dilewati {skipped}, error {errors}.",
+      "detachClientsSelectLabel": "Klien untuk dilepas",
       "exportLinksTitle": "Ekspor tautan inbound",
       "exportLinksTitle": "Ekspor tautan inbound",
       "exportSubsTitle": "Ekspor tautan langganan",
       "exportSubsTitle": "Ekspor tautan langganan",
       "exportAllLinksTitle": "Ekspor semua tautan inbound",
       "exportAllLinksTitle": "Ekspor semua tautan inbound",
@@ -306,7 +332,7 @@
       "destinationPort": "Port Tujuan",
       "destinationPort": "Port Tujuan",
       "targetAddress": "Alamat Target",
       "targetAddress": "Alamat Target",
       "monitorDesc": "Biarkan kosong untuk mendengarkan semua IP",
       "monitorDesc": "Biarkan kosong untuk mendengarkan semua IP",
-      "meansNoLimit": "= Unlimited. (unit: GB)",
+      "meansNoLimit": "= Tanpa batas. (satuan: GB)",
       "totalFlow": "Total Aliran",
       "totalFlow": "Total Aliran",
       "leaveBlankToNeverExpire": "Biarkan kosong untuk tidak pernah kedaluwarsa",
       "leaveBlankToNeverExpire": "Biarkan kosong untuk tidak pernah kedaluwarsa",
       "noRecommendKeepDefault": "Disarankan untuk tetap menggunakan pengaturan default",
       "noRecommendKeepDefault": "Disarankan untuk tetap menggunakan pengaturan default",
@@ -341,6 +367,7 @@
       "IPLimitlogDesc": "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)",
       "IPLimitlogDesc": "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)",
       "IPLimitlogclear": "Hapus Log",
       "IPLimitlogclear": "Hapus Log",
       "setDefaultCert": "Atur Sertifikat dari Panel",
       "setDefaultCert": "Atur Sertifikat dari Panel",
+      "setDefaultCertEmpty": "Tidak ada sertifikat yang dikonfigurasi untuk panel. Atur dulu di Pengaturan.",
       "streamTab": "Stream",
       "streamTab": "Stream",
       "securityTab": "Keamanan",
       "securityTab": "Keamanan",
       "sniffingTab": "Sniffing",
       "sniffingTab": "Sniffing",
@@ -369,7 +396,6 @@
       },
       },
       "telegramDesc": "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau ({'@'}userinfobot)",
       "telegramDesc": "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau ({'@'}userinfobot)",
       "subscriptionDesc": "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien.",
       "subscriptionDesc": "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien.",
-      "info": "Info",
       "same": "Sama",
       "same": "Sama",
       "inboundData": "Data Masuk",
       "inboundData": "Data Masuk",
       "exportInbound": "Ekspor Masuk",
       "exportInbound": "Ekspor Masuk",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Terjadi kesalahan saat mendapatkan sertifikat mldsa65.",
         "getNewmldsa65Error": "Terjadi kesalahan saat mendapatkan sertifikat mldsa65.",
         "getNewVlessEncError": "Terjadi kesalahan saat mendapatkan sertifikat VlessEnc."
         "getNewVlessEncError": "Terjadi kesalahan saat mendapatkan sertifikat VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Naik",
+        "moveDown": "Turun",
+        "addAll": "Tambah semua",
+        "addAllFallbackTooltip": "Tambahkan baris fallback untuk setiap inbound yang memenuhi syarat dan belum terhubung",
+        "peers": "Peers",
+        "addPeer": "Tambah peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Hanya Windows. CIDR ditambahkan otomatis ke tabel routing sistem agar trafik yang cocok melewati TUN.",
+        "autoOutboundsInterface": "Interface outbound otomatis",
+        "autoOutboundsInterfaceTooltip": "Interface fisik untuk trafik outbound. Gunakan 'auto' untuk deteksi; otomatis aktif saat Auto system routes diatur.",
+        "rewriteAddress": "Tulis ulang alamat",
+        "rewritePort": "Tulis ulang port",
+        "allowedNetwork": "Jaringan yang diizinkan",
+        "followRedirect": "Ikuti redirect",
+        "accounts": "Akun",
+        "allowTransparent": "Izinkan transparan",
+        "encryptionMethod": "Metode enkripsi",
+        "visionTestseed": "Vision testseed",
+        "version": "Versi",
+        "udpIdleTimeout": "UDP idle timeout (d)",
+        "masquerade": "Masquerade",
+        "type": "Tipe",
+        "upstreamUrl": "URL Upstream",
+        "rewriteHost": "Tulis ulang Host",
+        "skipTlsVerify": "Lewati verifikasi TLS",
+        "directory": "Direktori",
+        "statusCode": "Kode status",
+        "body": "Body",
+        "headers": "Header",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Versi permintaan",
+        "requestMethod": "Metode permintaan",
+        "requestPath": "Path permintaan",
+        "requestHeaders": "Header permintaan",
+        "responseVersion": "Versi respons",
+        "responseStatus": "Status respons",
+        "responseReason": "Alasan respons",
+        "responseHeaders": "Header respons",
+        "heartbeatPeriod": "Periode heartbeat",
+        "serviceName": "Nama layanan",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Maks. upload ter-buffer",
+        "maxUploadSize": "Ukuran upload maks. (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Maks. byte header server",
+        "paddingBytes": "Byte Padding",
+        "uplinkHttpMethod": "Metode HTTP Uplink",
+        "paddingObfsMode": "Mode obfs Padding",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Posisi Padding",
+        "paddingMethod": "Metode Padding",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Tanpa header SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Uplink (MB/s)",
+        "downlinkMbps": "Downlink (MB/s)",
+        "cwndMultiplier": "Pengganda CWND",
+        "maxSendingWindow": "Maks. jendela pengiriman",
+        "externalProxy": "Proxy eksternal",
+        "sniPlaceholder": "SNI (default = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Default",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Hanya V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For tepercaya",
+        "addressPortStrategy": "Strategi alamat+port",
+        "tryDelayMs": "Penundaan percobaan (ms)",
+        "prioritizeIPv6": "Prioritaskan IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Maks. percobaan bersamaan",
+        "customSockopt": "Sockopt kustom",
+        "addCustomOption": "Tambah opsi kustom",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Otomatis",
+        "minMaxVersion": "Versi Min/Maks",
+        "rejectUnknownSni": "Tolak SNI tidak dikenal",
+        "disableSystemRoot": "Nonaktifkan System Root",
+        "sessionResumption": "Lanjutkan sesi",
+        "oneTimeLoading": "Pemuatan sekali",
+        "usageOption": "Opsi penggunaan",
+        "buildChain": "Bangun rantai",
+        "echKey": "ECH key",
+        "echConfig": "Konfig ECH",
+        "getNewEchCert": "Dapatkan sertifikat ECH baru",
+        "show": "Tampilkan",
+        "xver": "Xver",
+        "target": "Target",
+        "maxTimeDiff": "Maks. selisih waktu (ms)",
+        "minClientVer": "Min. versi klien",
+        "maxClientVer": "Maks. versi klien",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Dapatkan sertifikat baru",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Dapatkan Seed baru"
+      },
+      "info": {
+        "mode": "Mode",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Nama interface",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Interface outbound",
+        "autoSystemRoutes": "Rute sistem otomatis",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN tanpa kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Konfig Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Permintaan",
           "request": "Permintaan",
@@ -456,6 +615,20 @@
       "days": "Hari",
       "days": "Hari",
       "renew": "Perpanjangan otomatis",
       "renew": "Perpanjangan otomatis",
       "renewDesc": "Perpanjangan otomatis setelah kedaluwarsa. (0 = nonaktif) (satuan: hari)",
       "renewDesc": "Perpanjangan otomatis setelah kedaluwarsa. (0 = nonaktif) (satuan: hari)",
+      "searchPlaceholder": "Cari email, komentar, sub ID, UUID, kata sandi, auth…",
+      "filterTitle": "Filter klien",
+      "clearAllFilters": "Hapus semua",
+      "sortOldest": "Terlama dulu",
+      "sortNewest": "Terbaru dulu",
+      "sortRecentlyUpdated": "Baru saja diperbarui",
+      "sortRecentlyOnline": "Baru saja online",
+      "sortEmailAZ": "Email A→Z",
+      "sortEmailZA": "Email Z→A",
+      "sortMostTraffic": "Trafik terbanyak",
+      "sortHighestRemaining": "Tersisa terbanyak",
+      "sortExpiringSoonest": "Segera kedaluwarsa",
+      "has": "Memiliki",
+      "hasNot": "Tidak memiliki",
       "title": "Klien",
       "title": "Klien",
       "actions": "Aksi",
       "actions": "Aksi",
       "totalGB": "Total Kirim/Terima (GB)",
       "totalGB": "Total Kirim/Terima (GB)",
@@ -466,6 +639,9 @@
       "subId": "ID Langganan",
       "subId": "ID Langganan",
       "online": "Online",
       "online": "Online",
       "email": "Email",
       "email": "Email",
+      "group": "Grup",
+      "groupDesc": "Label logis untuk mengelompokkan klien terkait (mis. tim, pelanggan, wilayah). Dapat difilter dari toolbar.",
+      "groupPlaceholder": "mis. customer-a",
       "comment": "Komentar",
       "comment": "Komentar",
       "traffic": "Lalu lintas",
       "traffic": "Lalu lintas",
       "offline": "Offline",
       "offline": "Offline",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Reset lalu lintas semua klien",
       "resetAllTraffics": "Reset lalu lintas semua klien",
       "resetAllTrafficsTitle": "Reset lalu lintas semua klien?",
       "resetAllTrafficsTitle": "Reset lalu lintas semua klien?",
       "resetAllTrafficsContent": "Penghitung kirim/terima setiap klien turun ke nol. Kuota dan kedaluwarsa tidak terpengaruh. Tidak dapat dibatalkan.",
       "resetAllTrafficsContent": "Penghitung kirim/terima setiap klien turun ke nol. Kuota dan kedaluwarsa tidak terpengaruh. Tidak dapat dibatalkan.",
-      "empty": "Belum ada klien — tambahkan satu untuk memulai.",
       "deleteConfirmTitle": "Hapus klien {email}?",
       "deleteConfirmTitle": "Hapus klien {email}?",
       "deleteConfirmContent": "Tindakan ini menghapus klien dari setiap inbound terlampir dan menghapus catatan lalu lintasnya. Tidak dapat dibatalkan.",
       "deleteConfirmContent": "Tindakan ini menghapus klien dari setiap inbound terlampir dan menghapus catatan lalu lintasnya. Tidak dapat dibatalkan.",
       "deleteSelected": "Hapus ({count})",
       "deleteSelected": "Hapus ({count})",
       "adjustSelected": "Sesuaikan ({count})",
       "adjustSelected": "Sesuaikan ({count})",
+      "subLinksSelected": "Tautan sub ({count})",
+      "addToGroupTitle": "Tambahkan {count} klien ke grup",
+      "addToGroupTooltip": "Pilih grup yang ada atau ketik nama baru. Gunakan Ungroup untuk menghapus klien dari grup saat ini.",
+      "addToGroupPlaceholder": "Nama grup",
+      "addToGroupSuccessToast": "{count} klien ditambahkan ke {group}",
+      "ungroupSuccessToast": "Grup dihapus dari {count} klien",
+      "ungroup": "Lepaskan grup",
+      "ungroupConfirmTitle": "Hapus {count} klien dari grupnya?",
+      "ungroupConfirmContent": "Menghapus label grup dari setiap klien terpilih. Klien tetap dipertahankan (gunakan Delete untuk menghapus sepenuhnya).",
+      "addToGroup": "Tambahkan ke grup",
+      "attach": "Lampirkan",
+      "adjust": "Atur",
+      "subLinks": "Tautan sub",
+      "selectedCount": "{count} dipilih",
+      "attachSelected": "Lampirkan ({count})",
+      "attachToInboundsTitle": "Lampirkan {count} klien ke inbound",
+      "attachToInboundsDesc": "Melampirkan {count} klien terpilih (UUID/kata sandi sama dan trafik bersama) ke inbound terpilih. Lampiran yang ada tetap dipertahankan.",
+      "attachToInboundsTargets": "Inbound tujuan",
+      "attachToInboundsNoTargets": "Tidak ada inbound multi-pengguna untuk dilampirkan.",
+      "detachSelected": "Lepas ({count})",
+      "detach": "Lepas",
+      "detachFromInboundsTitle": "Lepas {count} klien dari inbound",
+      "detachFromInboundsDesc": "Menghapus {count} klien terpilih dari inbound terpilih. Pasangan di mana klien tidak terlampir akan dilewati secara diam-diam. Catatan klien dipertahankan (gunakan Delete untuk menghapus sepenuhnya).",
+      "detachFromInboundsTargets": "Inbound untuk dilepas",
+      "detachFromInboundsNoTargets": "Tidak ada inbound multi-pengguna.",
+      "detachFromInboundsResult": "Dilepas {detached}, dilewati {skipped}.",
+      "detachFromInboundsResultMixed": "Dilepas {detached}, dilewati {skipped}, error {errors}.",
+      "subLinksTitle": "Tautan sub ({count})",
+      "subLinkColumn": "URL Langganan",
+      "subJsonLinkColumn": "URL JSON Langganan",
+      "subLinksCopyAll": "Salin semua",
+      "subLinksCopiedAll": "{count} tautan disalin",
+      "subLinksEmpty": "Tidak ada klien terpilih yang memiliki ID langganan.",
+      "subLinksDisabled": "Layanan langganan dinonaktifkan.",
+      "subLinksDisabledHint": "Aktifkan langganan di Pengaturan Panel → Langganan untuk membuat tautan.",
       "bulkDeleteConfirmTitle": "Hapus {count} klien?",
       "bulkDeleteConfirmTitle": "Hapus {count} klien?",
       "bulkDeleteConfirmContent": "Setiap klien yang dipilih dihapus dari semua inbound terlampir dan catatan lalu lintasnya dihapus. Tidak dapat dibatalkan.",
       "bulkDeleteConfirmContent": "Setiap klien yang dipilih dihapus dari semua inbound terlampir dan catatan lalu lintasnya dihapus. Tidak dapat dibatalkan.",
       "bulkAdjustTitle": "Sesuaikan {count} klien",
       "bulkAdjustTitle": "Sesuaikan {count} klien",
@@ -505,9 +715,10 @@
       "delDepletedConfirmTitle": "Hapus klien yang habis?",
       "delDepletedConfirmTitle": "Hapus klien yang habis?",
       "delDepletedConfirmContent": "Hapus setiap klien yang kuota lalu lintasnya habis atau yang masa berlakunya telah berakhir. Tidak dapat dibatalkan.",
       "delDepletedConfirmContent": "Hapus setiap klien yang kuota lalu lintasnya habis atau yang masa berlakunya telah berakhir. Tidak dapat dibatalkan.",
       "auth": "Auth",
       "auth": "Auth",
-      "hysteriaAuth": "Auth Hysteria",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
+      "vmessSecurity": "Keamanan VMess",
       "reverseTag": "Reverse tag",
       "reverseTag": "Reverse tag",
       "reverseTagPlaceholder": "Reverse tag opsional",
       "reverseTagPlaceholder": "Reverse tag opsional",
       "telegramId": "ID pengguna Telegram",
       "telegramId": "ID pengguna Telegram",
@@ -528,10 +739,48 @@
         "delDepleted": "{count} klien habis dihapus"
         "delDepleted": "{count} klien habis dihapus"
       }
       }
     },
     },
+    "groups": {
+      "title": "Grup",
+      "name": "Nama",
+      "clientCount": "Klien di grup",
+      "totalGroups": "Total grup",
+      "totalGroupedClients": "Klien dengan grup",
+      "emptyGroups": "Grup kosong",
+      "addGroup": "Tambah grup",
+      "createSuccess": "Grup «{name}» dibuat.",
+      "rename": "Ubah nama",
+      "renameTitle": "Ubah nama {name}",
+      "renameCollision": "Grup bernama «{name}» sudah ada.",
+      "renameSuccess": "Grup diubah namanya pada {count} klien.",
+      "deleteConfirmTitle": "Hapus grup {name}?",
+      "deleteConfirmContent": "Ini menghapus grup dan label-nya dari {count} klien. Klien itu sendiri tidak dihapus.",
+      "deleteSuccess": "Grup dihapus dari {count} klien.",
+      "resetTraffic": "Reset trafik",
+      "resetConfirmTitle": "Reset trafik grup {name}?",
+      "resetConfirmContent": "Ini mengatur ulang up/down ke 0 untuk semua {count} klien di grup ini.",
+      "resetSuccess": "Trafik direset untuk {count} klien.",
+      "adjustSuccess": "{count} klien di {name} disesuaikan.",
+      "emptyForAction": "Grup ini belum memiliki klien.",
+      "deleteGroupOnly": "Hapus grup (pertahankan klien)",
+      "deleteClients": "Hapus klien di grup",
+      "deleteClientsConfirmTitle": "Hapus semua klien di {name}?",
+      "deleteClientsConfirmContent": "Ini akan menghapus {count} klien secara permanen beserta catatan trafiknya. Label grup juga dihapus. Tidak dapat dibatalkan.",
+      "deleteClientsSuccess": "{count} klien dihapus.",
+      "deleteClientsMixed": "{ok} dihapus, {failed} dilewati",
+      "addToGroup": "Tambah klien…",
+      "addToGroupTitle": "Tambah klien ke grup «{name}»",
+      "addToGroupDesc": "Pilih klien untuk ditambahkan ke grup ini. Lampiran inbound yang ada tetap dipertahankan; hanya label grup yang berubah. Klien yang sudah ada di grup ini tidak ditampilkan.",
+      "addToGroupEmpty": "Tidak ada klien lain untuk ditambahkan.",
+      "addToGroupResult": "{count} klien ditambahkan ke {name}.",
+      "removeFromGroup": "Hapus klien…",
+      "removeFromGroupTitle": "Hapus klien dari grup «{name}»",
+      "removeFromGroupDesc": "Pilih anggota untuk dihapus dari grup ini. Klien tetap dipertahankan (gunakan «Hapus klien di grup» untuk menghapus sepenuhnya).",
+      "removeFromGroupResult": "{count} klien dihapus dari {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Node",
       "title": "Node",
       "addNode": "Tambah Node",
       "addNode": "Tambah Node",
-      "editNode": "Edit Node",
+      "editNode": "Edit node",
       "totalNodes": "Total Node",
       "totalNodes": "Total Node",
       "onlineNodes": "Online",
       "onlineNodes": "Online",
       "offlineNodes": "Offline",
       "offlineNodes": "Offline",
@@ -543,7 +792,7 @@
       "scheme": "Skema",
       "scheme": "Skema",
       "address": "Alamat",
       "address": "Alamat",
       "port": "Port",
       "port": "Port",
-      "basePath": "Base Path",
+      "basePath": "Path dasar",
       "apiToken": "Token API",
       "apiToken": "Token API",
       "apiTokenPlaceholder": "Token dari halaman Pengaturan panel jarak jauh",
       "apiTokenPlaceholder": "Token dari halaman Pengaturan panel jarak jauh",
       "apiTokenHint": "Panel jarak jauh menampilkan token API-nya di Pengaturan → Token API.",
       "apiTokenHint": "Panel jarak jauh menampilkan token API-nya di Pengaturan → Token API.",
@@ -590,7 +839,7 @@
       "title": "Pengaturan Panel",
       "title": "Pengaturan Panel",
       "save": "Simpan",
       "save": "Simpan",
       "infoDesc": "Setiap perubahan yang dibuat di sini perlu disimpan. Harap restart panel untuk menerapkan perubahan.",
       "infoDesc": "Setiap perubahan yang dibuat di sini perlu disimpan. Harap restart panel untuk menerapkan perubahan.",
-      "restartPanel": "Restart Panel",
+      "restartPanel": "Mulai ulang panel",
       "restartPanelDesc": "Apakah Anda yakin ingin merestart panel? Jika Anda tidak dapat mengakses panel setelah merestart, lihat info log panel di server.",
       "restartPanelDesc": "Apakah Anda yakin ingin merestart panel? Jika Anda tidak dapat mengakses panel setelah merestart, lihat info log panel di server.",
       "restartPanelSuccess": "Panel berhasil dimulai ulang",
       "restartPanelSuccess": "Panel berhasil dimulai ulang",
       "actions": "Tindakan",
       "actions": "Tindakan",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Path berkas kunci publik untuk panel web. (dimulai dengan ‘/‘)",
       "publicKeyPathDesc": "Path berkas kunci publik untuk panel web. (dimulai dengan ‘/‘)",
       "privateKeyPath": "Path Kunci Privat",
       "privateKeyPath": "Path Kunci Privat",
       "privateKeyPathDesc": "Path berkas kunci privat untuk panel web. (dimulai dengan ‘/‘)",
       "privateKeyPathDesc": "Path berkas kunci privat untuk panel web. (dimulai dengan ‘/‘)",
-      "panelUrlPath": "URI Path",
+      "panelUrlPath": "Path URI",
       "panelUrlPathDesc": "URI path untuk panel web. (dimulai dengan ‘/‘ dan diakhiri dengan ‘/‘)",
       "panelUrlPathDesc": "URI path untuk panel web. (dimulai dengan ‘/‘ dan diakhiri dengan ‘/‘)",
       "pageSize": "Ukuran Halaman",
       "pageSize": "Ukuran Halaman",
       "pageSizeDesc": "Tentukan ukuran halaman untuk tabel masuk. (0 = nonaktif)",
       "pageSizeDesc": "Tentukan ukuran halaman untuk tabel masuk. (0 = nonaktif)",
+      "panelProxy": "Proxy jaringan panel",
+      "panelProxyDesc": "Mengarahkan permintaan keluar panel sendiri (pembaruan geo, pemeriksaan versi Xray/panel, Telegram) melalui proxy ini untuk melewati pemfilteran GitHub/Telegram di sisi server. Menerima socks5:// atau http(s)://, mis. inbound SOCKS lokal Xray. Kosongkan untuk koneksi langsung.",
       "remarkModel": "Model Catatan & Karakter Pemisah",
       "remarkModel": "Model Catatan & Karakter Pemisah",
       "datepicker": "Jenis Kalender",
       "datepicker": "Jenis Kalender",
       "datepickerPlaceholder": "Pilih tanggal",
       "datepickerPlaceholder": "Pilih tanggal",
@@ -634,7 +885,7 @@
       "telegramTokenDesc": "Token bot Telegram yang diperoleh dari '{'@'}BotFather'.",
       "telegramTokenDesc": "Token bot Telegram yang diperoleh dari '{'@'}BotFather'.",
       "telegramProxy": "Proxy SOCKS",
       "telegramProxy": "Proxy SOCKS",
       "telegramProxyDesc": "Mengaktifkan proxy SOCKS5 untuk terhubung ke Telegram. (sesuaikan pengaturan sesuai panduan)",
       "telegramProxyDesc": "Mengaktifkan proxy SOCKS5 untuk terhubung ke Telegram. (sesuaikan pengaturan sesuai panduan)",
-      "telegramAPIServer": "Telegram API Server",
+      "telegramAPIServer": "Server API Telegram",
       "telegramAPIServerDesc": "Server API Telegram yang akan digunakan. Biarkan kosong untuk menggunakan server default.",
       "telegramAPIServerDesc": "Server API Telegram yang akan digunakan. Biarkan kosong untuk menggunakan server default.",
       "telegramChatId": "ID Obrolan Admin",
       "telegramChatId": "ID Obrolan Admin",
       "telegramChatIdDesc": "ID Obrolan Admin Telegram. (dipisahkan koma)(dapatkan di sini {'@'}userinfobot) atau (gunakan perintah '/id' di bot)",
       "telegramChatIdDesc": "ID Obrolan Admin Telegram. (dipisahkan koma)(dapatkan di sini {'@'}userinfobot) atau (gunakan perintah '/id' di bot)",
@@ -658,6 +909,8 @@
       "subEnable": "Aktifkan Layanan Langganan",
       "subEnable": "Aktifkan Layanan Langganan",
       "subEnableDesc": "Mengaktifkan layanan langganan.",
       "subEnableDesc": "Mengaktifkan layanan langganan.",
       "subJsonEnable": "Aktifkan/Nonaktifkan endpoint langganan JSON secara mandiri.",
       "subJsonEnable": "Aktifkan/Nonaktifkan endpoint langganan JSON secara mandiri.",
+      "subJsonEnableTitle": "Langganan JSON",
+      "subClashEnableTitle": "Langganan Clash / Mihomo",
       "subTitle": "Judul Langganan",
       "subTitle": "Judul Langganan",
       "subTitleDesc": "Judul yang ditampilkan di klien VPN",
       "subTitleDesc": "Judul yang ditampilkan di klien VPN",
       "subSupportUrl": "URL Dukungan",
       "subSupportUrl": "URL Dukungan",
@@ -678,7 +931,7 @@
       "subCertPathDesc": "Path berkas kunci publik untuk layanan langganan. (dimulai dengan ‘/‘)",
       "subCertPathDesc": "Path berkas kunci publik untuk layanan langganan. (dimulai dengan ‘/‘)",
       "subKeyPath": "Path Kunci Privat",
       "subKeyPath": "Path Kunci Privat",
       "subKeyPathDesc": "Path berkas kunci privat untuk layanan langganan. (dimulai dengan ‘/‘)",
       "subKeyPathDesc": "Path berkas kunci privat untuk layanan langganan. (dimulai dengan ‘/‘)",
-      "subPath": "URI Path",
+      "subPath": "Path URI",
       "subPathDesc": "URI path untuk layanan langganan. (dimulai dengan ‘/‘ dan diakhiri dengan ‘/‘)",
       "subPathDesc": "URI path untuk layanan langganan. (dimulai dengan ‘/‘ dan diakhiri dengan ‘/‘)",
       "subDomain": "Domain Pendengar",
       "subDomain": "Domain Pendengar",
       "subDomainDesc": "Nama domain untuk layanan langganan. (biarkan kosong untuk mendengarkan semua domain dan IP)",
       "subDomainDesc": "Nama domain untuk layanan langganan. (biarkan kosong untuk mendengarkan semua domain dan IP)",
@@ -693,7 +946,7 @@
       "subURI": "URI Proxy Terbalik",
       "subURI": "URI Proxy Terbalik",
       "subURIDesc": "Path URI dari URL langganan untuk digunakan di belakang proxy.",
       "subURIDesc": "Path URI dari URL langganan untuk digunakan di belakang proxy.",
       "externalTrafficInformEnable": "Informasikan API eksternal pada setiap pembaruan lalu lintas.",
       "externalTrafficInformEnable": "Informasikan API eksternal pada setiap pembaruan lalu lintas.",
-      "externalTrafficInformEnableDesc": "Inform external API on every traffic update.",
+      "externalTrafficInformEnableDesc": "Beritahu API eksternal setiap kali ada pembaruan trafik.",
       "externalTrafficInformURI": "Lalu Lintas Eksternal Menginformasikan URI",
       "externalTrafficInformURI": "Lalu Lintas Eksternal Menginformasikan URI",
       "externalTrafficInformURIDesc": "Pembaruan lalu lintas dikirim ke URI ini.",
       "externalTrafficInformURIDesc": "Pembaruan lalu lintas dikirim ke URI ini.",
       "restartXrayOnClientDisable": "Nyalakan Ulang Xray Setelah Nonaktif Otomatis",
       "restartXrayOnClientDisable": "Nyalakan Ulang Xray Setelah Nonaktif Otomatis",
@@ -703,6 +956,54 @@
       "fragmentSett": "Pengaturan Fragmentasi",
       "fragmentSett": "Pengaturan Fragmentasi",
       "noisesDesc": "Aktifkan Noises.",
       "noisesDesc": "Aktifkan Noises.",
       "noisesSett": "Pengaturan Noises",
       "noisesSett": "Pengaturan Noises",
+      "trustedProxyCidrs": "CIDR proxy tepercaya",
+      "trustedProxyCidrsDesc": "IP/CIDR (dipisahkan koma) yang diizinkan mengatur header forwarded host, proto, dan client IP.",
+      "ldap": {
+        "enable": "Aktifkan sinkronisasi LDAP",
+        "host": "LDAP host",
+        "port": "Port LDAP",
+        "useTls": "Gunakan TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Terkonfigurasi; biarkan kosong untuk mempertahankan kata sandi saat ini.",
+        "passwordUnconfigured": "Tidak terkonfigurasi.",
+        "passwordPlaceholder": "Terkonfigurasi — masukkan nilai baru untuk menggantikan",
+        "baseDn": "Base DN",
+        "userFilter": "Filter pengguna",
+        "userAttr": "Atribut pengguna (username/email)",
+        "vlessField": "Atribut flag VLESS",
+        "flagField": "Atribut flag umum (opsional)",
+        "flagFieldDesc": "Jika diatur, menimpa flag VLESS — mis. shadowInactive.",
+        "truthyValues": "Nilai truthy",
+        "truthyValuesDesc": "Dipisahkan koma; default: true,1,yes,on",
+        "invertFlag": "Balik flag",
+        "invertFlagDesc": "Aktifkan saat atribut berarti «dinonaktifkan» (mis. shadowInactive).",
+        "syncSchedule": "Jadwal sinkronisasi",
+        "syncScheduleDesc": "String mirip cron, mis. @every 1m",
+        "inboundTags": "Tag inbound",
+        "inboundTagsDesc": "Inbound di mana sinkronisasi LDAP dapat membuat/menghapus klien secara otomatis.",
+        "noInbounds": "Tidak ada inbound. Buat dulu di Inbound.",
+        "autoCreate": "Buat klien otomatis",
+        "autoDelete": "Hapus klien otomatis",
+        "defaultTotalGb": "Total default (GB)",
+        "defaultExpiryDays": "Kedaluwarsa default (hari)",
+        "defaultIpLimit": "Batas IP default"
+      },
+      "subFormats": {
+        "packets": "Paket",
+        "length": "Panjang",
+        "interval": "Interval",
+        "maxSplit": "Maks. pembagian",
+        "noises": "Noise",
+        "noiseItem": "Noise №{n}",
+        "type": "Tipe",
+        "packet": "Paket",
+        "delayMs": "Penundaan (ms)",
+        "applyTo": "Terapkan ke",
+        "addNoise": "+ Noise",
+        "concurrency": "Konkurensi",
+        "xudpConcurrency": "Konkurensi xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada.",
       "muxDesc": "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada.",
       "muxSett": "Pengaturan Mux",
       "muxSett": "Pengaturan Mux",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "Konfigurasi Xray",
       "title": "Konfigurasi Xray",
       "save": "Simpan",
       "save": "Simpan",
-      "restart": "Restart Xray",
+      "restart": "Mulai ulang Xray",
       "restartSuccess": "Xray berhasil diluncurkan ulang",
       "restartSuccess": "Xray berhasil diluncurkan ulang",
+      "restartOutputTitle": "Output mulai ulang Xray",
+      "restartConfirmTitle": "Mulai ulang xray?",
+      "restartConfirmContent": "Memuat ulang layanan xray dengan konfigurasi tersimpan.",
       "stopSuccess": "Xray telah berhasil dihentikan",
       "stopSuccess": "Xray telah berhasil dihentikan",
       "restartError": "Terjadi kesalahan saat memulai ulang Xray.",
       "restartError": "Terjadi kesalahan saat memulai ulang Xray.",
       "stopError": "Terjadi kesalahan saat menghentikan Xray.",
       "stopError": "Terjadi kesalahan saat menghentikan Xray.",
@@ -765,7 +1069,7 @@
       "advancedTemplate": "Lanjutan",
       "advancedTemplate": "Lanjutan",
       "generalConfigs": "Strategi Umum",
       "generalConfigs": "Strategi Umum",
       "generalConfigsDesc": "Opsi ini akan menentukan penyesuaian strategi umum.",
       "generalConfigsDesc": "Opsi ini akan menentukan penyesuaian strategi umum.",
-      "logConfigs": "Catatan",
+      "logConfigs": "Log",
       "logConfigsDesc": "Log dapat mempengaruhi efisiensi server Anda. Disarankan untuk mengaktifkannya dengan bijak hanya jika diperlukan",
       "logConfigsDesc": "Log dapat mempengaruhi efisiensi server Anda. Disarankan untuk mengaktifkannya dengan bijak hanya jika diperlukan",
       "blockConfigsDesc": "Opsi ini akan memblokir lalu lintas berdasarkan protokol dan situs web yang diminta.",
       "blockConfigsDesc": "Opsi ini akan memblokir lalu lintas berdasarkan protokol dan situs web yang diminta.",
       "basicRouting": "Perutean Dasar",
       "basicRouting": "Perutean Dasar",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "URL tes outbound",
       "outboundTestUrl": "URL tes outbound",
       "outboundTestUrlDesc": "URL yang digunakan saat menguji konektivitas outbound",
       "outboundTestUrlDesc": "URL yang digunakan saat menguji konektivitas outbound",
       "Torrent": "Blokir Protokol BitTorrent",
       "Torrent": "Blokir Protokol BitTorrent",
-      "Inbounds": "Masuk",
+      "Inbounds": "Inbound",
       "InboundsDesc": "Menerima klien tertentu.",
       "InboundsDesc": "Menerima klien tertentu.",
-      "Outbounds": "Keluar",
+      "Outbounds": "Outbound",
       "Balancers": "Penyeimbang",
       "Balancers": "Penyeimbang",
+      "balancerTagRequired": "Tag wajib diisi",
+      "balancerSelectorRequired": "Pilih setidaknya satu outbound",
       "OutboundsDesc": "Atur jalur lalu lintas keluar.",
       "OutboundsDesc": "Atur jalur lalu lintas keluar.",
       "Routings": "Aturan Pengalihan",
       "Routings": "Aturan Pengalihan",
       "RoutingsDesc": "Prioritas setiap aturan penting!",
       "RoutingsDesc": "Prioritas setiap aturan penting!",
@@ -832,6 +1138,73 @@
         "edit": "Edit Aturan",
         "edit": "Edit Aturan",
         "useComma": "Item yang dipisahkan koma"
         "useComma": "Item yang dipisahkan koma"
       },
       },
+      "routing": {
+        "dragToReorder": "Seret untuk mengurutkan ulang"
+      },
+      "ruleForm": {
+        "sourceIps": "IP sumber",
+        "sourcePort": "Port sumber",
+        "vlessRoute": "Rute VLESS",
+        "attributes": "Atribut",
+        "value": "Nilai",
+        "user": "Pengguna",
+        "inboundTags": "Tag inbound",
+        "outboundTag": "Tag outbound",
+        "balancerTag": "Tag balancer",
+        "balancerTagTooltip": "Mengarahkan trafik melalui salah satu balancer yang dikonfigurasi"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Tag sudah digunakan oleh outbound lain",
+        "tagRequired": "Tag wajib diisi",
+        "tagPlaceholder": "tag-unik",
+        "localIpPlaceholder": "IP lokal",
+        "addressRequired": "Alamat wajib diisi",
+        "portRequired": "Port wajib diisi",
+        "optional": "opsional",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "Versi UoT",
+        "inboundTag": "Tag inbound",
+        "inboundTagPlaceholder": "tag inbound yang digunakan dalam aturan routing",
+        "responseType": "Tipe respons",
+        "rewriteNetwork": "Tulis ulang jaringan",
+        "unchanged": "(tidak berubah)",
+        "unchangedAddress": "(tidak berubah) mis. 1.1.1.1",
+        "rules": "Aturan",
+        "ruleN": "Aturan {n}",
+        "action": "Aksi",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Aturan akhir",
+        "overrideXrayPrivateIp": "Timpa blok IP privat default Xray",
+        "blockDelay": "Penundaan blokir (ms)",
+        "reverseSniffing": "Sniffing terbalik",
+        "workers": "Workers",
+        "reserved": "Dicadangkan",
+        "minUploadInterval": "Min. interval upload (ms)",
+        "maxUploadSizeBytes": "Ukuran upload maks. (byte)",
+        "uplinkChunkSize": "Ukuran chunk Uplink",
+        "noGrpcHeader": "Tanpa header gRPC",
+        "maxConcurrency": "Maks. konkurensi",
+        "maxConnections": "Maks. koneksi",
+        "maxReuseTimes": "Maks. pemakaian ulang",
+        "maxRequestTimes": "Maks. permintaan",
+        "maxReusableSecs": "Maks. detik dapat dipakai ulang",
+        "keepAlivePeriod": "Periode keep alive",
+        "authPassword": "Kata sandi auth",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "nama server",
+        "verifyPeerName": "Verifikasi nama peer",
+        "pinnedSha256": "SHA256 pinned",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Interval keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Interface",
+        "ipv6Only": "Hanya IPv6",
+        "acceptProxyProtocol": "Terima proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (d)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Tambahkan Keluar",
         "addOutbound": "Tambahkan Keluar",
         "addReverse": "Tambahkan Revers",
         "addReverse": "Tambahkan Revers",
@@ -846,7 +1219,7 @@
         "reverse": "Revers",
         "reverse": "Revers",
         "domain": "Domain",
         "domain": "Domain",
         "type": "Tipe",
         "type": "Tipe",
-        "bridge": "Jembatan",
+        "bridge": "Bridge",
         "portal": "Portal",
         "portal": "Portal",
         "link": "Tautan",
         "link": "Tautan",
         "intercon": "Interkoneksi",
         "intercon": "Interkoneksi",
@@ -860,6 +1233,8 @@
         "testSuccess": "Tes berhasil",
         "testSuccess": "Tes berhasil",
         "testFailed": "Tes gagal",
         "testFailed": "Tes gagal",
         "testError": "Gagal menguji outbound",
         "testError": "Gagal menguji outbound",
+        "testModeTooltip": "TCP: probe dial-only cepat. HTTP: permintaan penuh via xray.",
+        "testAll": "Tes semua",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Token Akses",
         "accessToken": "Token Akses",
         "country": "Negara",
         "country": "Negara",
@@ -874,8 +1249,18 @@
         "editBalancer": "Sunting Penyeimbang",
         "editBalancer": "Sunting Penyeimbang",
         "balancerStrategy": "Strategi",
         "balancerStrategy": "Strategi",
         "balancerSelectors": "Penyeleksi",
         "balancerSelectors": "Penyeleksi",
-        "tag": "Menandai",
+        "tag": "Tag",
         "tagDesc": "Label Unik",
         "tagDesc": "Label Unik",
+        "tagDuplicate": "Tag sudah digunakan oleh balancer lain",
+        "tagPlaceholder": "tag balancer unik",
+        "selector": "Selector",
+        "fallback": "Fallback",
+        "expected": "Diharapkan",
+        "expectedPlaceholder": "jumlah node optimal",
+        "maxRtt": "Maks. RTT",
+        "tolerance": "Toleransi",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "BalancerTag dan outboundTag tidak dapat digunakan secara bersamaan. Jika digunakan secara bersamaan, hanya outboundTag yang akan berfungsi."
         "balancerDesc": "BalancerTag dan outboundTag tidak dapat digunakan secara bersamaan. Jika digunakan secara bersamaan, hanya outboundTag yang akan berfungsi."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Level Pengguna",
         "userLevel": "Level Pengguna",
         "userLevelDesc": "Semua koneksi yang dibuat melalui inbound ini akan menggunakan level pengguna ini. Standar adalah 0"
         "userLevelDesc": "Semua koneksi yang dibuat melalui inbound ini akan menggunakan level pengguna ini. Standar adalah 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Kunci privat",
+        "noServers": "Tidak ada server ditemukan untuk negara yang dipilih",
+        "noPublicKey": "Server yang dipilih tidak mengumumkan kunci publik NordLynx.",
+        "outboundAdded": "Outbound NordVPN ditambahkan",
+        "outboundUpdated": "Outbound NordVPN diperbarui"
+      },
+      "warp": {
+        "licenseError": "Gagal mengatur lisensi WARP.",
+        "fetchFirst": "Ambil konfig WARP terlebih dahulu.",
+        "createAccount": "Buat akun WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID perangkat",
+        "licenseKey": "Kunci lisensi",
+        "privateKey": "Kunci privat",
+        "deleteAccount": "Hapus akun",
+        "settings": "Pengaturan",
+        "licenseKeyLabel": "Kunci lisensi WARP / WARP+",
+        "key": "Kunci",
+        "keyPlaceholder": "kunci WARP+ 26 karakter",
+        "accountInfo": "Info akun",
+        "deviceName": "Nama perangkat",
+        "deviceModel": "Model perangkat",
+        "deviceEnabled": "Perangkat aktif",
+        "accountType": "Tipe akun",
+        "role": "Peran",
+        "warpPlusData": "Data WARP+",
+        "quota": "Kuota",
+        "usage": "Penggunaan",
+        "addOutbound": "Tambah outbound"
+      },
       "dns": {
       "dns": {
         "enable": "Aktifkan DNS",
         "enable": "Aktifkan DNS",
         "enableDesc": "Aktifkan server DNS bawaan",
         "enableDesc": "Aktifkan server DNS bawaan",
@@ -911,7 +1328,7 @@
         "strategyDesc": "Strategi keseluruhan untuk menyelesaikan nama domain",
         "strategyDesc": "Strategi keseluruhan untuk menyelesaikan nama domain",
         "add": "Tambahkan Server",
         "add": "Tambahkan Server",
         "edit": "Sunting Server",
         "edit": "Sunting Server",
-        "domains": "Domains",
+        "domains": "Domain",
         "expectIPs": "IP yang Diharapkan",
         "expectIPs": "IP yang Diharapkan",
         "unexpectIPs": "IP tak terduga",
         "unexpectIPs": "IP tak terduga",
         "useSystemHosts": "Gunakan Hosts Sistem",
         "useSystemHosts": "Gunakan Hosts Sistem",
@@ -1042,7 +1459,7 @@
       "inbound_client_data_id": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
       "inbound_client_data_id": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
       "inbound_client_data_pass": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
       "inbound_client_data_pass": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
       "cancel": "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄",
       "cancel": "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄",
-      "error_add_client": "⚠️ Kesalahan:\n\n {{ .error }}",
+      "error_add_client": "⚠️ Error:\n\n {{ .error }}",
       "using_default_value": "Oke, saya akan tetap menggunakan nilai default. 😊",
       "using_default_value": "Oke, saya akan tetap menggunakan nilai default. 😊",
       "incorrect_input": "Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫",
       "incorrect_input": "Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫",
       "AreYouSure": "Apakah kamu yakin? 🤔",
       "AreYouSure": "Apakah kamu yakin? 🤔",
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Pilih Inbound"
       "chooseInbound": "Pilih Inbound"
     }
     }
   }
   }
-}
+}

+ 469 - 52
web/translation/ja-JP.json

@@ -8,15 +8,22 @@
   "save": "保存",
   "save": "保存",
   "logout": "ログアウト",
   "logout": "ログアウト",
   "create": "作成",
   "create": "作成",
+  "add": "追加",
+  "remove": "削除",
   "update": "更新",
   "update": "更新",
   "copy": "コピー",
   "copy": "コピー",
   "copied": "コピー済み",
   "copied": "コピー済み",
+  "more": "もっと",
   "download": "ダウンロード",
   "download": "ダウンロード",
   "remark": "備考",
   "remark": "備考",
   "enable": "有効化",
   "enable": "有効化",
   "protocol": "プロトコル",
   "protocol": "プロトコル",
   "search": "検索",
   "search": "検索",
-  "filter": "フィルター",
+  "filter": "フィルタ",
+  "all": "すべて",
+  "from": "から",
+  "to": "まで",
+  "done": "完了",
   "loading": "読み込み中...",
   "loading": "読み込み中...",
   "refresh": "更新",
   "refresh": "更新",
   "clear": "クリア",
   "clear": "クリア",
@@ -41,7 +48,7 @@
   "transmission": "伝送",
   "transmission": "伝送",
   "host": "ホスト",
   "host": "ホスト",
   "path": "パス",
   "path": "パス",
-  "camouflage": "偽装",
+  "camouflage": "難読化",
   "status": "ステータス",
   "status": "ステータス",
   "enabled": "有効",
   "enabled": "有効",
   "disabled": "無効",
   "disabled": "無効",
@@ -95,11 +102,12 @@
     "dark": "ダーク",
     "dark": "ダーク",
     "ultraDark": "ウルトラダーク",
     "ultraDark": "ウルトラダーク",
     "dashboard": "ダッシュボード",
     "dashboard": "ダッシュボード",
-    "inbounds": "インバウンド一覧",
+    "inbounds": "インバウンド",
     "clients": "クライアント",
     "clients": "クライアント",
+    "groups": "グループ",
     "nodes": "ノード",
     "nodes": "ノード",
     "settings": "パネル設定",
     "settings": "パネル設定",
-    "xray": "Xray設定",
+    "xray": "Xray 設定",
     "apiDocs": "API ドキュメント",
     "apiDocs": "API ドキュメント",
     "logout": "ログアウト",
     "logout": "ログアウト",
     "link": "リンク管理",
     "link": "リンク管理",
@@ -123,7 +131,7 @@
       "cpu": "CPU",
       "cpu": "CPU",
       "logicalProcessors": "論理プロセッサ",
       "logicalProcessors": "論理プロセッサ",
       "frequency": "周波数",
       "frequency": "周波数",
-      "swap": "スワップ",
+      "swap": "Swap",
       "storage": "ストレージ",
       "storage": "ストレージ",
       "memory": "RAM",
       "memory": "RAM",
       "threads": "スレッド",
       "threads": "スレッド",
@@ -241,7 +249,7 @@
       "getConfigError": "設定ファイルの取得中にエラーが発生しました"
       "getConfigError": "設定ファイルの取得中にエラーが発生しました"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "インバウンド一覧",
+      "title": "インバウンド",
       "totalDownUp": "総アップロード / ダウンロード",
       "totalDownUp": "総アップロード / ダウンロード",
       "totalUsage": "総使用量",
       "totalUsage": "総使用量",
       "inboundCount": "インバウンド数",
       "inboundCount": "インバウンド数",
@@ -252,7 +260,7 @@
       "deployTo": "デプロイ先",
       "deployTo": "デプロイ先",
       "localPanel": "ローカルパネル",
       "localPanel": "ローカルパネル",
       "fallbacks": {
       "fallbacks": {
-        "title": "フォールバック",
+        "title": "Fallbacks",
         "help": "このインバウンドへの接続がどのクライアントにも一致しない場合、別のインバウンドへルーティングします。下から子インバウンドを選ぶと、ルーティング項目(SNI / ALPN / Path / xver)はその子のトランスポートから自動的に埋められます — ほとんどの構成で追加の調整は不要です。各子インバウンドは 127.0.0.1 で security=none をリッスンする必要があります。",
         "help": "このインバウンドへの接続がどのクライアントにも一致しない場合、別のインバウンドへルーティングします。下から子インバウンドを選ぶと、ルーティング項目(SNI / ALPN / Path / xver)はその子のトランスポートから自動的に埋められます — ほとんどの構成で追加の調整は不要です。各子インバウンドは 127.0.0.1 で security=none をリッスンする必要があります。",
         "empty": "フォールバックはまだありません",
         "empty": "フォールバックはまだありません",
         "add": "フォールバックを追加",
         "add": "フォールバックを追加",
@@ -273,11 +281,11 @@
       "portMap": "ポートマッピング",
       "portMap": "ポートマッピング",
       "traffic": "トラフィック",
       "traffic": "トラフィック",
       "details": "詳細情報",
       "details": "詳細情報",
-      "transportConfig": "トランスポート設定",
+      "transportConfig": "トランスポート",
       "expireDate": "有効期限",
       "expireDate": "有効期限",
       "createdAt": "作成",
       "createdAt": "作成",
       "updatedAt": "更新",
       "updatedAt": "更新",
-      "resetTraffic": "トラフィックリセット",
+      "resetTraffic": "トラフィックリセット",
       "addInbound": "インバウンド追加",
       "addInbound": "インバウンド追加",
       "generalActions": "一般操作",
       "generalActions": "一般操作",
       "modifyInbound": "インバウンド修正",
       "modifyInbound": "インバウンド修正",
@@ -292,6 +300,24 @@
       "delAllClients": "すべてのクライアントを削除",
       "delAllClients": "すべてのクライアントを削除",
       "delAllClientsConfirmTitle": "「{remark}」から {count} 件のクライアントをすべて削除しますか?",
       "delAllClientsConfirmTitle": "「{remark}」から {count} 件のクライアントをすべて削除しますか?",
       "delAllClientsConfirmContent": "このインバウンドからすべてのクライアントを削除し、トラフィックレコードも破棄します。インバウンド自体は保持されます。この操作は取り消せません。",
       "delAllClientsConfirmContent": "このインバウンドからすべてのクライアントを削除し、トラフィックレコードも破棄します。インバウンド自体は保持されます。この操作は取り消せません。",
+      "attachClients": "クライアントをアタッチ…",
+      "addClientsToGroup": "クライアントをグループに追加…",
+      "attachClientsTitle": "「{remark}」のクライアントをアタッチ",
+      "attachClientsDesc": "同じ {count} クライアント(同じ UUID/パスワードと共有トラフィック)を選択したインバウンドにアタッチします。このインバウンドにも残ります。",
+      "attachClientsTargets": "ターゲットインバウンド",
+      "attachClientsNoTargets": "アタッチ可能な互換インバウンドがありません。",
+      "attachClientsResult": "アタッチ {attached}、スキップ {skipped}。",
+      "attachClientsResultMixed": "アタッチ {attached}、スキップ {skipped}、エラー {errors}。",
+      "attachClientsSelectLabel": "アタッチするクライアント",
+      "attachClientsSearchPlaceholder": "メールまたはコメントを検索",
+      "attachClientsStatusDisabled": "無効",
+      "attachClientsSelectedCount": "{total} 中 {selected} 選択中",
+      "detachClients": "クライアントをデタッチ",
+      "detachClientsTitle": "「{remark}」のクライアントをデタッチ",
+      "detachClientsDesc": "選択したクライアントをこのインバウンドのみから外します。クライアントレコードは保持されます (完全に削除するには Delete を使用)。ソースには合計 {count} クライアントがあります。",
+      "detachClientsResult": "デタッチ {detached}、スキップ {skipped}。",
+      "detachClientsResultMixed": "デタッチ {detached}、スキップ {skipped}、エラー {errors}。",
+      "detachClientsSelectLabel": "デタッチするクライアント",
       "exportLinksTitle": "インバウンドリンクのエクスポート",
       "exportLinksTitle": "インバウンドリンクのエクスポート",
       "exportSubsTitle": "サブスクリプションリンクのエクスポート",
       "exportSubsTitle": "サブスクリプションリンクのエクスポート",
       "exportAllLinksTitle": "全インバウンドリンクのエクスポート",
       "exportAllLinksTitle": "全インバウンドリンクのエクスポート",
@@ -306,7 +332,7 @@
       "destinationPort": "宛先ポート",
       "destinationPort": "宛先ポート",
       "targetAddress": "宛先アドレス",
       "targetAddress": "宛先アドレス",
       "monitorDesc": "空白にするとすべてのIPを監視",
       "monitorDesc": "空白にするとすべてのIPを監視",
-      "meansNoLimit": "= 無制限(単位:GB)",
+      "meansNoLimit": "= 無制限。(単位: GB)",
       "totalFlow": "総トラフィック",
       "totalFlow": "総トラフィック",
       "leaveBlankToNeverExpire": "空白にすると期限なし",
       "leaveBlankToNeverExpire": "空白にすると期限なし",
       "noRecommendKeepDefault": "デフォルト値を保持することをお勧めします",
       "noRecommendKeepDefault": "デフォルト値を保持することをお勧めします",
@@ -333,7 +359,7 @@
       "delDepletedClients": "トラフィックが尽きたクライアントを削除",
       "delDepletedClients": "トラフィックが尽きたクライアントを削除",
       "delDepletedClientsTitle": "トラフィックが尽きたクライアントを削除",
       "delDepletedClientsTitle": "トラフィックが尽きたクライアントを削除",
       "delDepletedClientsContent": "トラフィックが尽きたすべてのクライアントを削除してもよろしいですか?",
       "delDepletedClientsContent": "トラフィックが尽きたすべてのクライアントを削除してもよろしいですか?",
-      "email": "メールアドレス",
+      "email": "メール",
       "emailDesc": "メールアドレスは一意でなければなりません",
       "emailDesc": "メールアドレスは一意でなければなりません",
       "IPLimit": "IP制限",
       "IPLimit": "IP制限",
       "IPLimitDesc": "設定値を超えるとインバウンドトラフィックが無効になります。(0 = 無効)",
       "IPLimitDesc": "設定値を超えるとインバウンドトラフィックが無効になります。(0 = 無効)",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "IP履歴ログ(無効なインバウンドトラフィックを有効にするには、ログをクリアしてください)",
       "IPLimitlogDesc": "IP履歴ログ(無効なインバウンドトラフィックを有効にするには、ログをクリアしてください)",
       "IPLimitlogclear": "ログをクリア",
       "IPLimitlogclear": "ログをクリア",
       "setDefaultCert": "パネル設定から証明書を設定",
       "setDefaultCert": "パネル設定から証明書を設定",
-      "streamTab": "ストリーム",
+      "setDefaultCertEmpty": "パネル用の証明書が設定されていません。先に設定から指定してください。",
+      "streamTab": "Stream",
       "securityTab": "セキュリティ",
       "securityTab": "セキュリティ",
-      "sniffingTab": "スニッフィング",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "メタデータのみ",
       "sniffingMetadataOnly": "メタデータのみ",
       "sniffingRouteOnly": "ルーティングのみ",
       "sniffingRouteOnly": "ルーティングのみ",
       "sniffingIpsExcluded": "除外する IP",
       "sniffingIpsExcluded": "除外する IP",
@@ -361,15 +388,14 @@
         "allHelp": "すべてのフィールドを含むインバウンドオブジェクト全体を 1 つのエディターで編集します。",
         "allHelp": "すべてのフィールドを含むインバウンドオブジェクト全体を 1 つのエディターで編集します。",
         "settings": "設定",
         "settings": "設定",
         "settingsHelp": "Xray settings ブロックのラッパー:",
         "settingsHelp": "Xray settings ブロックのラッパー:",
-        "sniffing": "スニッフィング",
+        "sniffing": "Sniffing",
         "sniffingHelp": "Xray sniffing ブロックのラッパー:",
         "sniffingHelp": "Xray sniffing ブロックのラッパー:",
-        "stream": "ストリーム",
+        "stream": "Stream",
         "streamHelp": "Xray stream ブロックのラッパー:",
         "streamHelp": "Xray stream ブロックのラッパー:",
         "jsonErrorPrefix": "高度な JSON"
         "jsonErrorPrefix": "高度な JSON"
       },
       },
       "telegramDesc": "TelegramチャットIDを提供してください。(ボットで'/id'コマンドを使用)または({'@'}userinfobot)",
       "telegramDesc": "TelegramチャットIDを提供してください。(ボットで'/id'コマンドを使用)または({'@'}userinfobot)",
       "subscriptionDesc": "サブスクリプションURLを見つけるには、“詳細情報”に移動してください。また、複数のクライアントに同じ名前を使用することができます。",
       "subscriptionDesc": "サブスクリプションURLを見つけるには、“詳細情報”に移動してください。また、複数のクライアントに同じ名前を使用することができます。",
-      "info": "情報",
       "same": "同じ",
       "same": "同じ",
       "inboundData": "インバウンドデータ",
       "inboundData": "インバウンドデータ",
       "exportInbound": "インバウンドルールをエクスポート",
       "exportInbound": "インバウンドルールをエクスポート",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "mldsa65証明書の取得中にエラーが発生しました。",
         "getNewmldsa65Error": "mldsa65証明書の取得中にエラーが発生しました。",
         "getNewVlessEncError": "VlessEnc証明書の取得中にエラーが発生しました。"
         "getNewVlessEncError": "VlessEnc証明書の取得中にエラーが発生しました。"
       },
       },
+      "form": {
+        "moveUp": "上へ",
+        "moveDown": "下へ",
+        "addAll": "すべて追加",
+        "addAllFallbackTooltip": "まだ接続されていないすべての対象インバウンドに対し fallback 行を追加",
+        "peers": "Peers",
+        "addPeer": "peer を追加",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Windows のみ。CIDR はシステムルーティングテーブルに自動追加され、一致するトラフィックは TUN を経由します。",
+        "autoOutboundsInterface": "自動アウトバウンドインターフェース",
+        "autoOutboundsInterfaceTooltip": "アウトバウンドトラフィック用の物理インターフェース。検出には 'auto' を使用; Auto system routes が設定されていると自動的に有効。",
+        "rewriteAddress": "アドレス書き換え",
+        "rewritePort": "ポート書き換え",
+        "allowedNetwork": "許可されたネットワーク",
+        "followRedirect": "リダイレクトに従う",
+        "accounts": "アカウント",
+        "allowTransparent": "透過を許可",
+        "encryptionMethod": "暗号化方式",
+        "visionTestseed": "Vision testseed",
+        "version": "バージョン",
+        "udpIdleTimeout": "UDP idle timeout (秒)",
+        "masquerade": "Masquerade",
+        "type": "種類",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Host 書き換え",
+        "skipTlsVerify": "TLS 検証をスキップ",
+        "directory": "ディレクトリ",
+        "statusCode": "ステータスコード",
+        "body": "Body",
+        "headers": "ヘッダー",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "リクエストバージョン",
+        "requestMethod": "リクエストメソッド",
+        "requestPath": "リクエストパス",
+        "requestHeaders": "リクエストヘッダー",
+        "responseVersion": "レスポンスバージョン",
+        "responseStatus": "レスポンスステータス",
+        "responseReason": "レスポンス理由",
+        "responseHeaders": "レスポンスヘッダー",
+        "heartbeatPeriod": "ハートビート間隔",
+        "serviceName": "サービス名",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "最大バッファアップロード",
+        "maxUploadSize": "最大アップロードサイズ (バイト)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "サーバー最大ヘッダーバイト",
+        "paddingBytes": "Padding バイト",
+        "uplinkHttpMethod": "Uplink HTTP メソッド",
+        "paddingObfsMode": "Padding 難読化モード",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding 配置",
+        "paddingMethod": "Padding 方法",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "SSE ヘッダーなし",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "アップリンク (MB/s)",
+        "downlinkMbps": "ダウンリンク (MB/s)",
+        "cwndMultiplier": "CWND 倍率",
+        "maxSendingWindow": "最大送信ウィンドウ",
+        "externalProxy": "外部プロキシ",
+        "sniPlaceholder": "SNI (デフォルトは host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "デフォルト",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "V6 のみ",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "信頼できる X-Forwarded-For",
+        "addressPortStrategy": "アドレス+ポート戦略",
+        "tryDelayMs": "試行遅延 (ms)",
+        "prioritizeIPv6": "IPv6 優先",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "最大同時試行",
+        "customSockopt": "カスタム sockopt",
+        "addCustomOption": "カスタムオプション追加",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "自動",
+        "minMaxVersion": "最小/最大バージョン",
+        "rejectUnknownSni": "未知の SNI を拒否",
+        "disableSystemRoot": "System Root を無効化",
+        "sessionResumption": "セッション再開",
+        "oneTimeLoading": "一度のみ読み込み",
+        "usageOption": "使用オプション",
+        "buildChain": "Build Chain",
+        "echKey": "ECH key",
+        "echConfig": "ECH config",
+        "getNewEchCert": "新しい ECH 証明書を取得",
+        "show": "表示",
+        "xver": "Xver",
+        "target": "ターゲット",
+        "maxTimeDiff": "最大時間差 (ms)",
+        "minClientVer": "最小クライアントバージョン",
+        "maxClientVer": "最大クライアントバージョン",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "新しい証明書を取得",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "新しい Seed を取得"
+      },
+      "info": {
+        "mode": "モード",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "インターフェース名",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "アウトバウンドインターフェース",
+        "autoSystemRoutes": "自動システムルート",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "非カーネル TUN",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Peer {n} 設定"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "リクエスト",
           "request": "リクエスト",
@@ -456,6 +615,20 @@
       "days": "日",
       "days": "日",
       "renew": "自動更新",
       "renew": "自動更新",
       "renewDesc": "有効期限切れ後に自動更新します。(0 = 無効) (単位: 日)",
       "renewDesc": "有効期限切れ後に自動更新します。(0 = 無効) (単位: 日)",
+      "searchPlaceholder": "メール、コメント、sub ID、UUID、パスワード、auth を検索…",
+      "filterTitle": "クライアントをフィルタ",
+      "clearAllFilters": "すべてクリア",
+      "sortOldest": "古い順",
+      "sortNewest": "新しい順",
+      "sortRecentlyUpdated": "最近更新",
+      "sortRecentlyOnline": "最近オンライン",
+      "sortEmailAZ": "メール A→Z",
+      "sortEmailZA": "メール Z→A",
+      "sortMostTraffic": "トラフィック多い順",
+      "sortHighestRemaining": "残量多い順",
+      "sortExpiringSoonest": "もうすぐ期限切れ",
+      "has": "あり",
+      "hasNot": "なし",
       "title": "クライアント",
       "title": "クライアント",
       "actions": "操作",
       "actions": "操作",
       "totalGB": "送受信合計 (GB)",
       "totalGB": "送受信合計 (GB)",
@@ -466,6 +639,9 @@
       "subId": "サブスクリプション ID",
       "subId": "サブスクリプション ID",
       "online": "オンライン",
       "online": "オンライン",
       "email": "メール",
       "email": "メール",
+      "group": "グループ",
+      "groupDesc": "関連クライアントをまとめる論理ラベル(チーム、顧客、地域など)。ツールバーからフィルタ可能。",
+      "groupPlaceholder": "例: customer-a",
       "comment": "コメント",
       "comment": "コメント",
       "traffic": "トラフィック",
       "traffic": "トラフィック",
       "offline": "オフライン",
       "offline": "オフライン",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "すべてのクライアントのトラフィックをリセット",
       "resetAllTraffics": "すべてのクライアントのトラフィックをリセット",
       "resetAllTrafficsTitle": "すべてのクライアントのトラフィックをリセットしますか?",
       "resetAllTrafficsTitle": "すべてのクライアントのトラフィックをリセットしますか?",
       "resetAllTrafficsContent": "すべてのクライアントの送受信カウンターがゼロにリセットされます。クォータと有効期限には影響しません。元に戻せません。",
       "resetAllTrafficsContent": "すべてのクライアントの送受信カウンターがゼロにリセットされます。クォータと有効期限には影響しません。元に戻せません。",
-      "empty": "クライアントはまだいません — 1 つ追加して始めましょう。",
       "deleteConfirmTitle": "クライアント {email} を削除しますか?",
       "deleteConfirmTitle": "クライアント {email} を削除しますか?",
       "deleteConfirmContent": "クライアントを関連付けされたすべてのインバウンドから削除し、トラフィック記録も破棄します。元に戻せません。",
       "deleteConfirmContent": "クライアントを関連付けされたすべてのインバウンドから削除し、トラフィック記録も破棄します。元に戻せません。",
       "deleteSelected": "削除 ({count})",
       "deleteSelected": "削除 ({count})",
       "adjustSelected": "調整 ({count})",
       "adjustSelected": "調整 ({count})",
+      "subLinksSelected": "サブリンク ({count})",
+      "addToGroupTitle": "{count} クライアントをグループに追加",
+      "addToGroupTooltip": "既存のグループを選ぶか新しい名前を入力してください。Ungroup で現在のグループから外せます。",
+      "addToGroupPlaceholder": "グループ名",
+      "addToGroupSuccessToast": "{count} クライアントを {group} に追加しました",
+      "ungroupSuccessToast": "{count} クライアントのグループをクリアしました",
+      "ungroup": "グループ解除",
+      "ungroupConfirmTitle": "{count} クライアントをグループから外しますか?",
+      "ungroupConfirmContent": "選択したクライアントのグループラベルをクリアします。クライアント自体は保持されます (完全に削除するには Delete を使用)。",
+      "addToGroup": "グループに追加",
+      "attach": "アタッチ",
+      "adjust": "調整",
+      "subLinks": "サブリンク",
+      "selectedCount": "{count} 選択中",
+      "attachSelected": "アタッチ ({count})",
+      "attachToInboundsTitle": "{count} クライアントをインバウンドにアタッチ",
+      "attachToInboundsDesc": "選択した {count} クライアント(同じ UUID/パスワードと共有トラフィック)を選択したインバウンドにアタッチします。既存のアタッチは維持されます。",
+      "attachToInboundsTargets": "ターゲットインバウンド",
+      "attachToInboundsNoTargets": "アタッチ可能なマルチユーザーインバウンドがありません。",
+      "detachSelected": "デタッチ ({count})",
+      "detach": "デタッチ",
+      "detachFromInboundsTitle": "{count} クライアントをインバウンドからデタッチ",
+      "detachFromInboundsDesc": "選択した {count} クライアントを選択したインバウンドから外します。アタッチされていなかったペアは黙ってスキップされます。クライアントレコードは保持されます (完全に削除するには Delete を使用)。",
+      "detachFromInboundsTargets": "デタッチ対象のインバウンド",
+      "detachFromInboundsNoTargets": "マルチユーザーインバウンドがありません。",
+      "detachFromInboundsResult": "デタッチ {detached}、スキップ {skipped}。",
+      "detachFromInboundsResultMixed": "デタッチ {detached}、スキップ {skipped}、エラー {errors}。",
+      "subLinksTitle": "サブリンク ({count})",
+      "subLinkColumn": "サブスクリプション URL",
+      "subJsonLinkColumn": "サブスクリプション JSON URL",
+      "subLinksCopyAll": "すべてコピー",
+      "subLinksCopiedAll": "{count} リンクをコピーしました",
+      "subLinksEmpty": "選択したクライアントにはサブスクリプション ID がありません。",
+      "subLinksDisabled": "サブスクリプションサービスは無効です。",
+      "subLinksDisabledHint": "リンクを生成するにはパネル設定 → サブスクリプションで有効にしてください。",
       "bulkDeleteConfirmTitle": "{count} 件のクライアントを削除しますか?",
       "bulkDeleteConfirmTitle": "{count} 件のクライアントを削除しますか?",
       "bulkDeleteConfirmContent": "選択された各クライアントを関連付けされたすべてのインバウンドから削除し、トラフィック記録も破棄します。元に戻せません。",
       "bulkDeleteConfirmContent": "選択された各クライアントを関連付けされたすべてのインバウンドから削除し、トラフィック記録も破棄します。元に戻せません。",
       "bulkAdjustTitle": "{count} 件のクライアントを調整",
       "bulkAdjustTitle": "{count} 件のクライアントを調整",
@@ -505,9 +715,10 @@
       "delDepletedConfirmTitle": "使い切ったクライアントを削除しますか?",
       "delDepletedConfirmTitle": "使い切ったクライアントを削除しますか?",
       "delDepletedConfirmContent": "トラフィック上限に達したか有効期限が切れたクライアントをすべて削除します。元に戻せません。",
       "delDepletedConfirmContent": "トラフィック上限に達したか有効期限が切れたクライアントをすべて削除します。元に戻せません。",
       "auth": "Auth",
       "auth": "Auth",
-      "hysteriaAuth": "Auth (Hysteria)",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
+      "vmessSecurity": "VMess セキュリティ",
       "reverseTag": "Reverse tag",
       "reverseTag": "Reverse tag",
       "reverseTagPlaceholder": "任意の Reverse tag",
       "reverseTagPlaceholder": "任意の Reverse tag",
       "telegramId": "Telegram ユーザー ID",
       "telegramId": "Telegram ユーザー ID",
@@ -528,10 +739,48 @@
         "delDepleted": "使い切った {count} 件のクライアントを削除しました"
         "delDepleted": "使い切った {count} 件のクライアントを削除しました"
       }
       }
     },
     },
+    "groups": {
+      "title": "グループ",
+      "name": "名前",
+      "clientCount": "グループ内のクライアント",
+      "totalGroups": "グループ合計",
+      "totalGroupedClients": "グループのあるクライアント",
+      "emptyGroups": "空のグループ",
+      "addGroup": "グループ追加",
+      "createSuccess": "グループ「{name}」を作成しました。",
+      "rename": "名前変更",
+      "renameTitle": "{name} の名前を変更",
+      "renameCollision": "「{name}」という名前のグループは既に存在します。",
+      "renameSuccess": "{count} クライアントのグループ名を変更しました。",
+      "deleteConfirmTitle": "グループ {name} を削除?",
+      "deleteConfirmContent": "これはグループを削除し、{count} クライアントのラベルをクリアします。クライアント自体は削除されません。",
+      "deleteSuccess": "{count} クライアントのグループをクリアしました。",
+      "resetTraffic": "トラフィックをリセット",
+      "resetConfirmTitle": "グループ {name} のトラフィックをリセット?",
+      "resetConfirmContent": "このグループ内のすべての {count} クライアントの up/down をゼロにします。",
+      "resetSuccess": "{count} クライアントのトラフィックをリセットしました。",
+      "adjustSuccess": "{name} 内の {count} クライアントを調整しました。",
+      "emptyForAction": "このグループにはまだクライアントがありません。",
+      "deleteGroupOnly": "グループ削除 (クライアントは保持)",
+      "deleteClients": "グループのクライアントを削除",
+      "deleteClientsConfirmTitle": "{name} 内のすべてのクライアントを削除?",
+      "deleteClientsConfirmContent": "これは {count} クライアントとそのトラフィック記録を永久に削除します。グループラベルもクリアされます。取り消せません。",
+      "deleteClientsSuccess": "{count} クライアントを削除しました。",
+      "deleteClientsMixed": "{ok} 削除、{failed} スキップ",
+      "addToGroup": "クライアントを追加…",
+      "addToGroupTitle": "グループ「{name}」にクライアントを追加",
+      "addToGroupDesc": "このグループに追加するクライアントを選択してください。既存のインバウンドアタッチは保持され、グループラベルのみ変更されます。すでにこのグループにいるクライアントは表示されません。",
+      "addToGroupEmpty": "追加可能な他のクライアントはありません。",
+      "addToGroupResult": "{count} クライアントを {name} に追加しました。",
+      "removeFromGroup": "クライアントを削除…",
+      "removeFromGroupTitle": "グループ「{name}」からクライアントを削除",
+      "removeFromGroupDesc": "このグループから外すメンバーを選択してください。クライアント自体は保持されます (完全に削除するには「グループのクライアントを削除」を使用)。",
+      "removeFromGroupResult": "{count} クライアントを {name} から外しました。"
+    },
     "nodes": {
     "nodes": {
       "title": "ノード",
       "title": "ノード",
       "addNode": "ノードを追加",
       "addNode": "ノードを追加",
-      "editNode": "ノードを編集",
+      "editNode": "ノード編集",
       "totalNodes": "ノード総数",
       "totalNodes": "ノード総数",
       "onlineNodes": "オンライン",
       "onlineNodes": "オンライン",
       "offlineNodes": "オフライン",
       "offlineNodes": "オフライン",
@@ -544,7 +793,7 @@
       "address": "アドレス",
       "address": "アドレス",
       "port": "ポート",
       "port": "ポート",
       "basePath": "ベースパス",
       "basePath": "ベースパス",
-      "apiToken": "APIトークン",
+      "apiToken": "API トークン",
       "apiTokenPlaceholder": "リモートパネルの設定ページから取得したトークン",
       "apiTokenPlaceholder": "リモートパネルの設定ページから取得したトークン",
       "apiTokenHint": "リモートパネルでは、設定 → APIトークン でAPIトークンを確認できます。",
       "apiTokenHint": "リモートパネルでは、設定 → APIトークン でAPIトークンを確認できます。",
       "regenerate": "トークンを再生成",
       "regenerate": "トークンを再生成",
@@ -590,7 +839,7 @@
       "title": "パネル設定",
       "title": "パネル設定",
       "save": "保存",
       "save": "保存",
       "infoDesc": "ここでのすべての変更は、保存してパネルを再起動する必要があります",
       "infoDesc": "ここでのすべての変更は、保存してパネルを再起動する必要があります",
-      "restartPanel": "パネル再起動",
+      "restartPanel": "パネル再起動",
       "restartPanelDesc": "パネルを再起動してもよろしいですか?再起動後にパネルにアクセスできない場合は、サーバーでパネルログを確認してください",
       "restartPanelDesc": "パネルを再起動してもよろしいですか?再起動後にパネルにアクセスできない場合は、サーバーでパネルログを確認してください",
       "restartPanelSuccess": "パネルの再起動に成功しました",
       "restartPanelSuccess": "パネルの再起動に成功しました",
       "actions": "操作",
       "actions": "操作",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "デフォルトのベースパス \"/\" はよく知られています — ランダムなパスに変更してください。",
       "warnDefaultBasePath": "デフォルトのベースパス \"/\" はよく知られています — ランダムなパスに変更してください。",
       "warnDefaultSubPath": "デフォルトのサブスクリプションパス \"/sub/\" はよく知られています — 変更してください。",
       "warnDefaultSubPath": "デフォルトのサブスクリプションパス \"/sub/\" はよく知られています — 変更してください。",
       "warnDefaultJsonPath": "デフォルトの JSON サブスクリプションパス \"/json/\" はよく知られています — 変更してください。",
       "warnDefaultJsonPath": "デフォルトの JSON サブスクリプションパス \"/json/\" はよく知られています — 変更してください。",
-      "TGBotSettings": "Telegramボット設定",
+      "TGBotSettings": "Telegram Bot",
       "panelListeningIP": "パネル監視IP",
       "panelListeningIP": "パネル監視IP",
       "panelListeningIPDesc": "デフォルトではすべてのIPを監視する",
       "panelListeningIPDesc": "デフォルトではすべてのIPを監視する",
       "panelListeningDomain": "パネル監視ドメイン",
       "panelListeningDomain": "パネル監視ドメイン",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "'/'で始まる絶対パスを入力",
       "publicKeyPathDesc": "'/'で始まる絶対パスを入力",
       "privateKeyPath": "パネル証明書秘密鍵ファイルパス",
       "privateKeyPath": "パネル証明書秘密鍵ファイルパス",
       "privateKeyPathDesc": "'/'で始まる絶対パスを入力",
       "privateKeyPathDesc": "'/'で始まる絶対パスを入力",
-      "panelUrlPath": "パネルURLルートパス",
+      "panelUrlPath": "URI パス",
       "panelUrlPathDesc": "'/'で始まり、'/'で終わる必要があります",
       "panelUrlPathDesc": "'/'で始まり、'/'で終わる必要があります",
       "pageSize": "ページサイズ",
       "pageSize": "ページサイズ",
       "pageSizeDesc": "インバウンドテーブルのページサイズを定義します。0を設定すると無効化されます",
       "pageSizeDesc": "インバウンドテーブルのページサイズを定義します。0を設定すると無効化されます",
+      "panelProxy": "パネルネットワークプロキシ",
+      "panelProxyDesc": "パネル自体のアウトバウンドリクエスト (geo 更新、Xray/パネルバージョンチェック、Telegram) をこのプロキシ経由でルーティングし、サーバー側の GitHub/Telegram フィルタリングを回避します。socks5:// または http(s):// を受け付けます。例: ローカルの Xray SOCKS インバウンド。直接接続するには空のままにします。",
       "remarkModel": "備考モデルと区切り記号",
       "remarkModel": "備考モデルと区切り記号",
       "datepicker": "日付ピッカー",
       "datepicker": "日付ピッカー",
       "datepickerPlaceholder": "日付を選択",
       "datepickerPlaceholder": "日付を選択",
@@ -630,11 +881,11 @@
       "newPassword": "新しいパスワード",
       "newPassword": "新しいパスワード",
       "telegramBotEnable": "Telegramボットを有効にする",
       "telegramBotEnable": "Telegramボットを有効にする",
       "telegramBotEnableDesc": "Telegramボット機能を有効にする",
       "telegramBotEnableDesc": "Telegramボット機能を有効にする",
-      "telegramToken": "Telegramボットトークン",
+      "telegramToken": "Telegram トークン",
       "telegramTokenDesc": "'{'@'}BotFather'から取得したTelegramボットトークン",
       "telegramTokenDesc": "'{'@'}BotFather'から取得したTelegramボットトークン",
-      "telegramProxy": "SOCKS5プロキシ",
+      "telegramProxy": "SOCKS プロキシ",
       "telegramProxyDesc": "SOCKS5プロキシを有効にしてTelegramに接続する(ガイドに従って設定を調整)",
       "telegramProxyDesc": "SOCKS5プロキシを有効にしてTelegramに接続する(ガイドに従って設定を調整)",
-      "telegramAPIServer": "Telegram APIサーバー",
+      "telegramAPIServer": "Telegram API サーバー",
       "telegramAPIServerDesc": "使用するTelegram APIサーバー。空白の場合はデフォルトサーバーを使用する",
       "telegramAPIServerDesc": "使用するTelegram APIサーバー。空白の場合はデフォルトサーバーを使用する",
       "telegramChatId": "管理者チャットID",
       "telegramChatId": "管理者チャットID",
       "telegramChatIdDesc": "Telegram管理者チャットID(複数の場合はカンマで区切る){'@'}userinfobotで取得するか、ボットで'/id'コマンドを使用して取得する",
       "telegramChatIdDesc": "Telegram管理者チャットID(複数の場合はカンマで区切る){'@'}userinfobotで取得するか、ボットで'/id'コマンドを使用して取得する",
@@ -658,6 +909,8 @@
       "subEnable": "サブスクリプションサービスを有効にする",
       "subEnable": "サブスクリプションサービスを有効にする",
       "subEnableDesc": "サブスクリプションサービス機能を有効にする",
       "subEnableDesc": "サブスクリプションサービス機能を有効にする",
       "subJsonEnable": "JSON サブスクリプションのエンドポイントを個別に有効/無効にする。",
       "subJsonEnable": "JSON サブスクリプションのエンドポイントを個別に有効/無効にする。",
+      "subJsonEnableTitle": "JSON サブスクリプション",
+      "subClashEnableTitle": "Clash / Mihomo サブスクリプション",
       "subTitle": "サブスクリプションタイトル",
       "subTitle": "サブスクリプションタイトル",
       "subTitleDesc": "VPNクライアントに表示されるタイトル",
       "subTitleDesc": "VPNクライアントに表示されるタイトル",
       "subSupportUrl": "サポートURL",
       "subSupportUrl": "サポートURL",
@@ -678,7 +931,7 @@
       "subCertPathDesc": "サブスクリプションサービスで使用する公開鍵ファイルのパス('/'で始まる)",
       "subCertPathDesc": "サブスクリプションサービスで使用する公開鍵ファイルのパス('/'で始まる)",
       "subKeyPath": "秘密鍵パス",
       "subKeyPath": "秘密鍵パス",
       "subKeyPathDesc": "サブスクリプションサービスで使用する秘密鍵ファイルのパス('/'で始まる)",
       "subKeyPathDesc": "サブスクリプションサービスで使用する秘密鍵ファイルのパス('/'で始まる)",
-      "subPath": "URIパス",
+      "subPath": "URI パス",
       "subPathDesc": "サブスクリプションサービスで使用するURIパス('/'で始まり、'/'で終わる)",
       "subPathDesc": "サブスクリプションサービスで使用するURIパス('/'で始まり、'/'で終わる)",
       "subDomain": "監視ドメイン",
       "subDomain": "監視ドメイン",
       "subDomainDesc": "サブスクリプションサービスが監視するドメイン(空白にするとすべてのドメインとIPを監視)",
       "subDomainDesc": "サブスクリプションサービスが監視するドメイン(空白にするとすべてのドメインとIPを監視)",
@@ -693,7 +946,7 @@
       "subURI": "リバースプロキシURI",
       "subURI": "リバースプロキシURI",
       "subURIDesc": "プロキシ後ろのサブスクリプションURLのURIパスに使用する",
       "subURIDesc": "プロキシ後ろのサブスクリプションURLのURIパスに使用する",
       "externalTrafficInformEnable": "外部トラフィック情報",
       "externalTrafficInformEnable": "外部トラフィック情報",
-      "externalTrafficInformEnableDesc": "トラフィック更新ごとに外部 API に通知します。",
+      "externalTrafficInformEnableDesc": "トラフィック更新ごとに外部 API に通知。",
       "externalTrafficInformURI": "外部トラフィック通知 URI",
       "externalTrafficInformURI": "外部トラフィック通知 URI",
       "externalTrafficInformURIDesc": "トラフィックの更新ごとに外部 API に通知します。",
       "externalTrafficInformURIDesc": "トラフィックの更新ごとに外部 API に通知します。",
       "restartXrayOnClientDisable": "自動無効化後に Xray を再起動",
       "restartXrayOnClientDisable": "自動無効化後に Xray を再起動",
@@ -703,7 +956,55 @@
       "fragmentSett": "設定",
       "fragmentSett": "設定",
       "noisesDesc": "Noisesを有効にする",
       "noisesDesc": "Noisesを有効にする",
       "noisesSett": "Noises設定",
       "noisesSett": "Noises設定",
-      "mux": "マルチプレクサ",
+      "trustedProxyCidrs": "信頼できるプロキシ CIDR",
+      "trustedProxyCidrsDesc": "転送される host、proto、クライアント IP ヘッダーを設定可能な IP/CIDR (カンマ区切り)。",
+      "ldap": {
+        "enable": "LDAP 同期を有効化",
+        "host": "LDAP host",
+        "port": "LDAP ポート",
+        "useTls": "TLS (LDAPS) を使用",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "設定済み;現在のパスワードを保持するには空のままにします。",
+        "passwordUnconfigured": "未設定。",
+        "passwordPlaceholder": "設定済み — 置き換えるには新しい値を入力",
+        "baseDn": "Base DN",
+        "userFilter": "ユーザーフィルター",
+        "userAttr": "ユーザー属性 (username/email)",
+        "vlessField": "VLESS flag 属性",
+        "flagField": "汎用 flag 属性 (任意)",
+        "flagFieldDesc": "設定すると VLESS flag を上書きします — 例: shadowInactive。",
+        "truthyValues": "Truthy 値",
+        "truthyValuesDesc": "カンマ区切り;デフォルト: true,1,yes,on",
+        "invertFlag": "flag を反転",
+        "invertFlagDesc": "属性が「無効」を意味する場合に有効化 (例: shadowInactive)。",
+        "syncSchedule": "同期スケジュール",
+        "syncScheduleDesc": "cron 風の文字列、例 @every 1m",
+        "inboundTags": "インバウンドタグ",
+        "inboundTagsDesc": "LDAP 同期がクライアントを自動作成/削除できるインバウンド。",
+        "noInbounds": "インバウンドが見つかりません。先にインバウンドで作成してください。",
+        "autoCreate": "クライアントを自動作成",
+        "autoDelete": "クライアントを自動削除",
+        "defaultTotalGb": "デフォルト合計 (GB)",
+        "defaultExpiryDays": "デフォルト有効期限 (日)",
+        "defaultIpLimit": "デフォルト IP 制限"
+      },
+      "subFormats": {
+        "packets": "パケット",
+        "length": "長さ",
+        "interval": "間隔",
+        "maxSplit": "最大分割",
+        "noises": "ノイズ",
+        "noiseItem": "ノイズ №{n}",
+        "type": "種類",
+        "packet": "パケット",
+        "delayMs": "遅延 (ms)",
+        "applyTo": "適用先",
+        "addNoise": "+ ノイズ",
+        "concurrency": "並行数",
+        "xudpConcurrency": "xudp 並行数",
+        "xudpUdp443": "xudp UDP 443"
+      },
+      "mux": "Mux",
       "muxDesc": "確立されたストリーム内で複数の独立したストリームを伝送する",
       "muxDesc": "確立されたストリーム内で複数の独立したストリームを伝送する",
       "muxSett": "マルチプレクサ設定",
       "muxSett": "マルチプレクサ設定",
       "direct": "直接接続",
       "direct": "直接接続",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "Xray 設定",
       "title": "Xray 設定",
       "save": "保存",
       "save": "保存",
-      "restart": "Xray 再起動",
+      "restart": "Xray 再起動",
       "restartSuccess": "Xrayの再起動に成功しました",
       "restartSuccess": "Xrayの再起動に成功しました",
+      "restartOutputTitle": "Xray 再起動の出力",
+      "restartConfirmTitle": "xray を再起動?",
+      "restartConfirmContent": "保存された構成で xray サービスを再ロードします。",
       "stopSuccess": "Xrayが正常に停止しました",
       "stopSuccess": "Xrayが正常に停止しました",
       "restartError": "Xrayの再起動中にエラーが発生しました。",
       "restartError": "Xrayの再起動中にエラーが発生しました。",
       "stopError": "Xrayの停止中にエラーが発生しました。",
       "stopError": "Xrayの停止中にエラーが発生しました。",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "アウトバウンドテスト URL",
       "outboundTestUrl": "アウトバウンドテスト URL",
       "outboundTestUrlDesc": "アウトバウンド接続テストに使用する URL。既定値",
       "outboundTestUrlDesc": "アウトバウンド接続テストに使用する URL。既定値",
       "Torrent": "BitTorrent プロトコルをブロック",
       "Torrent": "BitTorrent プロトコルをブロック",
-      "Inbounds": "インバウンドルール",
+      "Inbounds": "インバウンド",
       "InboundsDesc": "特定のクライアントからのトラフィックを受け入れる",
       "InboundsDesc": "特定のクライアントからのトラフィックを受け入れる",
-      "Outbounds": "アウトバウンドルール",
+      "Outbounds": "アウトバウンド",
       "Balancers": "負荷分散",
       "Balancers": "負荷分散",
+      "balancerTagRequired": "タグは必須です",
+      "balancerSelectorRequired": "アウトバウンドを少なくとも1つ選んでください",
       "OutboundsDesc": "アウトバウンドトラフィックの送信方法を設定する",
       "OutboundsDesc": "アウトバウンドトラフィックの送信方法を設定する",
       "Routings": "ルーティングルール",
       "Routings": "ルーティングルール",
       "RoutingsDesc": "各ルールの優先順位が重要です",
       "RoutingsDesc": "各ルールの優先順位が重要です",
@@ -832,6 +1138,73 @@
         "edit": "ルール編集",
         "edit": "ルール編集",
         "useComma": "カンマ区切りの項目"
         "useComma": "カンマ区切りの項目"
       },
       },
+      "routing": {
+        "dragToReorder": "ドラッグして並べ替え"
+      },
+      "ruleForm": {
+        "sourceIps": "送信元 IP",
+        "sourcePort": "送信元ポート",
+        "vlessRoute": "VLESS ルート",
+        "attributes": "属性",
+        "value": "値",
+        "user": "ユーザー",
+        "inboundTags": "インバウンドタグ",
+        "outboundTag": "アウトバウンドタグ",
+        "balancerTag": "バランサータグ",
+        "balancerTagTooltip": "設定済みのロードバランサーの1つを通じてトラフィックをルーティング"
+      },
+      "outboundForm": {
+        "tagDuplicate": "このタグは他のアウトバウンドで使用されています",
+        "tagRequired": "タグは必須です",
+        "tagPlaceholder": "一意のタグ",
+        "localIpPlaceholder": "ローカル IP",
+        "addressRequired": "アドレスは必須です",
+        "portRequired": "ポートは必須です",
+        "optional": "任意",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "UoT バージョン",
+        "inboundTag": "インバウンドタグ",
+        "inboundTagPlaceholder": "ルーティングルールで使うインバウンドタグ",
+        "responseType": "レスポンスタイプ",
+        "rewriteNetwork": "ネットワーク書き換え",
+        "unchanged": "(変更なし)",
+        "unchangedAddress": "(変更なし) 例: 1.1.1.1",
+        "rules": "ルール",
+        "ruleN": "ルール {n}",
+        "action": "アクション",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "最終ルール",
+        "overrideXrayPrivateIp": "Xray のデフォルトプライベート IP ブロックを上書き",
+        "blockDelay": "ブロック遅延 (ms)",
+        "reverseSniffing": "逆 sniffing",
+        "workers": "Workers",
+        "reserved": "予約",
+        "minUploadInterval": "最小アップロード間隔 (ms)",
+        "maxUploadSizeBytes": "最大アップロードサイズ (バイト)",
+        "uplinkChunkSize": "Uplink チャンクサイズ",
+        "noGrpcHeader": "gRPC ヘッダーなし",
+        "maxConcurrency": "最大同時実行数",
+        "maxConnections": "最大接続数",
+        "maxReuseTimes": "最大再利用回数",
+        "maxRequestTimes": "最大リクエスト回数",
+        "maxReusableSecs": "最大再利用秒数",
+        "keepAlivePeriod": "keep alive 周期",
+        "authPassword": "Auth パスワード",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "サーバー名",
+        "verifyPeerName": "peer 名を検証",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "keep alive 間隔",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "インターフェース",
+        "ipv6Only": "IPv6 のみ",
+        "acceptProxyProtocol": "proxy protocol を受け入れる",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (秒)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "アウトバウンド追加",
         "addOutbound": "アウトバウンド追加",
         "addReverse": "リバース追加",
         "addReverse": "リバース追加",
@@ -846,8 +1219,8 @@
         "reverse": "リバース",
         "reverse": "リバース",
         "domain": "ドメイン",
         "domain": "ドメイン",
         "type": "タイプ",
         "type": "タイプ",
-        "bridge": "ブリッジ",
-        "portal": "ポータル",
+        "bridge": "Bridge",
+        "portal": "Portal",
         "link": "リンク",
         "link": "リンク",
         "intercon": "インターコネクション",
         "intercon": "インターコネクション",
         "settings": "設定",
         "settings": "設定",
@@ -860,6 +1233,8 @@
         "testSuccess": "テスト成功",
         "testSuccess": "テスト成功",
         "testFailed": "テスト失敗",
         "testFailed": "テスト失敗",
         "testError": "アウトバウンドのテストに失敗しました",
         "testError": "アウトバウンドのテストに失敗しました",
+        "testModeTooltip": "TCP: 高速 dial-only プローブ。HTTP: xray を経由した完全リクエスト。",
+        "testAll": "すべてテスト",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "アクセストークン",
         "accessToken": "アクセストークン",
         "country": "国",
         "country": "国",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "セレクター",
         "balancerSelectors": "セレクター",
         "tag": "タグ",
         "tag": "タグ",
         "tagDesc": "一意のタグ",
         "tagDesc": "一意のタグ",
+        "tagDuplicate": "このタグは他のバランサーで使用されています",
+        "tagPlaceholder": "一意のバランサータグ",
+        "selector": "セレクター",
+        "fallback": "Fallback",
+        "expected": "期待値",
+        "expectedPlaceholder": "最適ノード数",
+        "maxRtt": "最大 RTT",
+        "tolerance": "許容範囲",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "balancerTagとoutboundTagは同時に使用できません。同時に使用された場合、outboundTagのみが有効になります。"
         "balancerDesc": "balancerTagとoutboundTagは同時に使用できません。同時に使用された場合、outboundTagのみが有効になります。"
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "ユーザーレベル",
         "userLevel": "ユーザーレベル",
         "userLevelDesc": "このインバウンドを通じて確立されたすべての接続は、このユーザーレベルを使用します。デフォルトは 0 です"
         "userLevelDesc": "このインバウンドを通じて確立されたすべての接続は、このユーザーレベルを使用します。デフォルトは 0 です"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "秘密鍵",
+        "noServers": "選択した国のサーバーが見つかりません",
+        "noPublicKey": "選択したサーバーは NordLynx 公開鍵を公開していません。",
+        "outboundAdded": "NordVPN アウトバウンドを追加しました",
+        "outboundUpdated": "NordVPN アウトバウンドを更新しました"
+      },
+      "warp": {
+        "licenseError": "WARP ライセンスの設定に失敗しました。",
+        "fetchFirst": "先に WARP 構成を取得してください。",
+        "createAccount": "WARP アカウントを作成",
+        "accessToken": "Access token",
+        "deviceId": "デバイス ID",
+        "licenseKey": "ライセンスキー",
+        "privateKey": "秘密鍵",
+        "deleteAccount": "アカウントを削除",
+        "settings": "設定",
+        "licenseKeyLabel": "WARP / WARP+ ライセンスキー",
+        "key": "キー",
+        "keyPlaceholder": "26文字の WARP+ キー",
+        "accountInfo": "アカウント情報",
+        "deviceName": "デバイス名",
+        "deviceModel": "デバイスモデル",
+        "deviceEnabled": "デバイス有効",
+        "accountType": "アカウントタイプ",
+        "role": "役割",
+        "warpPlusData": "WARP+ データ",
+        "quota": "クォータ",
+        "usage": "使用量",
+        "addOutbound": "アウトバウンドを追加"
+      },
       "dns": {
       "dns": {
         "enable": "DNSを有効にする",
         "enable": "DNSを有効にする",
         "enableDesc": "組み込みDNSサーバーを有効にする",
         "enableDesc": "組み込みDNSサーバーを有効にする",
@@ -992,35 +1409,35 @@
       "2faFailed": "2FAエラー",
       "2faFailed": "2FAエラー",
       "report": "🕰 定期報告:{{ .RunTime }}\r\n",
       "report": "🕰 定期報告:{{ .RunTime }}\r\n",
       "datetime": "⏰ 日時:{{ .DateTime }}\r\n",
       "datetime": "⏰ 日時:{{ .DateTime }}\r\n",
-      "hostname": "💻 ホスト名:{{ .Hostname }}\r\n",
+      "hostname": "💻 ホスト: {{ .Hostname }}\r\n",
       "version": "🚀 X-UI バージョン:{{ .Version }}\r\n",
       "version": "🚀 X-UI バージョン:{{ .Version }}\r\n",
       "xrayVersion": "📡 Xray バージョン: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Xray バージョン: {{ .XrayVersion }}\r\n",
-      "ipv6": "🌐 IPv6{{ .IPv6 }}\r\n",
-      "ipv4": "🌐 IPv4{{ .IPv4 }}\r\n",
-      "ip": "🌐 IP{{ .IP }}\r\n",
-      "ips": "🔢 IPアドレス:\r\n{{ .IPs }}\r\n",
+      "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
+      "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
+      "ip": "🌐 IP: {{ .IP }}\r\n",
+      "ips": "🔢 IP:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ サーバー稼働時間:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ サーバー稼働時間:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 サーバー負荷:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 サーバー負荷:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 サーバーメモリ:{{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 TCP接続数:{{ .Count }}\r\n",
-      "udpCount": "🔸 UDP接続数:{{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 トラフィック:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 トラフィック:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Xrayステータス:{{ .State }}\r\n",
+      "xrayStatus": "ℹ️ ステータス: {{ .State }}\r\n",
       "username": "👤 ユーザー名:{{ .Username }}\r\n",
       "username": "👤 ユーザー名:{{ .Username }}\r\n",
       "reason": "❗️ 理由:{{ .Reason }}\r\n",
       "reason": "❗️ 理由:{{ .Reason }}\r\n",
       "time": "⏰ 時間:{{ .Time }}\r\n",
       "time": "⏰ 時間:{{ .Time }}\r\n",
-      "inbound": "📍 インバウンド{{ .Remark }}\r\n",
-      "port": "🔌 ポート{{ .Port }}\r\n",
+      "inbound": "📍 インバウンド: {{ .Remark }}\r\n",
+      "port": "🔌 ポート: {{ .Port }}\r\n",
       "expire": "📅 有効期限:{{ .Time }}\r\n",
       "expire": "📅 有効期限:{{ .Time }}\r\n",
       "expireIn": "📅 残り時間:{{ .Time }}\r\n",
       "expireIn": "📅 残り時間:{{ .Time }}\r\n",
       "active": "💡 有効:{{ .Enable }}\r\n",
       "active": "💡 有効:{{ .Enable }}\r\n",
       "enabled": "🚨 有効化済み:{{ .Enable }}\r\n",
       "enabled": "🚨 有効化済み:{{ .Enable }}\r\n",
       "online": "🌐 接続ステータス:{{ .Status }}\r\n",
       "online": "🌐 接続ステータス:{{ .Status }}\r\n",
       "lastOnline": "🔙 最終オンライン: {{ .Time }}\r\n",
       "lastOnline": "🔙 最終オンライン: {{ .Time }}\r\n",
-      "email": "📧 メール{{ .Email }}\r\n",
-      "upload": "🔼 アップロード↑{{ .Upload }}\r\n",
-      "download": "🔽 ダウンロード↓{{ .Download }}\r\n",
-      "total": "📊 合計{{ .UpDown }} / {{ .Total }}\r\n",
+      "email": "📧 メール: {{ .Email }}\r\n",
+      "upload": "🔼 アップロード: ↑{{ .Upload }}\r\n",
+      "download": "🔽 ダウンロード: ↓{{ .Download }}\r\n",
+      "total": "📊 合計: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 Telegramユーザー:{{ .TelegramID }}\r\n",
       "TGUser": "👤 Telegramユーザー:{{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 消耗済みの {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 消耗済みの {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 消耗済みの {{ .Type }} 数量:\r\n",
       "exhaustedCount": "🚨 消耗済みの {{ .Type }} 数量:\r\n",
@@ -1089,9 +1506,9 @@
       "use_default": "🏷️ デフォルトを使用",
       "use_default": "🏷️ デフォルトを使用",
       "change_id": "⚙️🔑 ID",
       "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 パスワード",
       "change_password": "⚙️🔑 パスワード",
-      "change_email": "⚙️📧 メールアドレス",
+      "change_email": "⚙️📧 メール",
       "change_comment": "⚙️💬 コメント",
       "change_comment": "⚙️💬 コメント",
-      "change_flow": "⚙️🚦 フロー",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "すべてのトラフィックをリセット",
       "ResetAllTraffics": "すべてのトラフィックをリセット",
       "SortedTrafficUsageReport": "ソートされたトラフィック使用レポート"
       "SortedTrafficUsageReport": "ソートされたトラフィック使用レポート"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "インバウンドを選択"
       "chooseInbound": "インバウンドを選択"
     }
     }
   }
   }
-}
+}

+ 444 - 27
web/translation/pt-BR.json

@@ -8,15 +8,22 @@
   "save": "Salvar",
   "save": "Salvar",
   "logout": "Sair",
   "logout": "Sair",
   "create": "Criar",
   "create": "Criar",
+  "add": "Adicionar",
+  "remove": "Remover",
   "update": "Atualizar",
   "update": "Atualizar",
   "copy": "Copiar",
   "copy": "Copiar",
   "copied": "Copiado",
   "copied": "Copiado",
+  "more": "mais",
   "download": "Baixar",
   "download": "Baixar",
   "remark": "Observação",
   "remark": "Observação",
   "enable": "Ativado",
   "enable": "Ativado",
   "protocol": "Protocolo",
   "protocol": "Protocolo",
   "search": "Pesquisar",
   "search": "Pesquisar",
   "filter": "Filtrar",
   "filter": "Filtrar",
+  "all": "Todos",
+  "from": "De",
+  "to": "Até",
+  "done": "Concluído",
   "loading": "Carregando...",
   "loading": "Carregando...",
   "refresh": "Atualizar",
   "refresh": "Atualizar",
   "clear": "Limpar",
   "clear": "Limpar",
@@ -27,7 +34,7 @@
   "check": "Verificar",
   "check": "Verificar",
   "indefinite": "Indeterminado",
   "indefinite": "Indeterminado",
   "unlimited": "Ilimitado",
   "unlimited": "Ilimitado",
-  "none": "Nada",
+  "none": "Nenhum",
   "qrCode": "Código QR",
   "qrCode": "Código QR",
   "info": "Mais Informações",
   "info": "Mais Informações",
   "edit": "Editar",
   "edit": "Editar",
@@ -39,7 +46,7 @@
   "encryption": "Criptografia",
   "encryption": "Criptografia",
   "useIPv4ForHost": "Usar IPv4 para o host",
   "useIPv4ForHost": "Usar IPv4 para o host",
   "transmission": "Transmissão",
   "transmission": "Transmissão",
-  "host": "Servidor",
+  "host": "Host",
   "path": "Caminho",
   "path": "Caminho",
   "camouflage": "Ofuscação",
   "camouflage": "Ofuscação",
   "status": "Status",
   "status": "Status",
@@ -95,11 +102,12 @@
     "dark": "Escuro",
     "dark": "Escuro",
     "ultraDark": "Ultra Escuro",
     "ultraDark": "Ultra Escuro",
     "dashboard": "Visão Geral",
     "dashboard": "Visão Geral",
-    "inbounds": "Inbounds",
+    "inbounds": "Entradas",
     "clients": "Clientes",
     "clients": "Clientes",
+    "groups": "Grupos",
     "nodes": "Nós",
     "nodes": "Nós",
-    "settings": "Panel Settings",
-    "xray": "Xray Configs",
+    "settings": "Configurações do Painel",
+    "xray": "Configurações Xray",
     "apiDocs": "Documentação da API",
     "apiDocs": "Documentação da API",
     "logout": "Sair",
     "logout": "Sair",
     "link": "Gerenciar",
     "link": "Gerenciar",
@@ -241,7 +249,7 @@
       "getConfigError": "Ocorreu um erro ao recuperar o arquivo de configuração"
       "getConfigError": "Ocorreu um erro ao recuperar o arquivo de configuração"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "Inbounds",
+      "title": "Entradas",
       "totalDownUp": "Total Enviado/Recebido",
       "totalDownUp": "Total Enviado/Recebido",
       "totalUsage": "Uso Total",
       "totalUsage": "Uso Total",
       "inboundCount": "Total de Inbounds",
       "inboundCount": "Total de Inbounds",
@@ -270,14 +278,14 @@
       },
       },
       "protocol": "Protocolo",
       "protocol": "Protocolo",
       "port": "Porta",
       "port": "Porta",
-      "portMap": "Porta Mapeada",
+      "portMap": "Mapeamento de portas",
       "traffic": "Tráfego",
       "traffic": "Tráfego",
       "details": "Detalhes",
       "details": "Detalhes",
       "transportConfig": "Transporte",
       "transportConfig": "Transporte",
       "expireDate": "Duração",
       "expireDate": "Duração",
       "createdAt": "Criado",
       "createdAt": "Criado",
       "updatedAt": "Atualizado",
       "updatedAt": "Atualizado",
-      "resetTraffic": "Redefinir Tráfego",
+      "resetTraffic": "Redefinir tráfego",
       "addInbound": "Adicionar Inbound",
       "addInbound": "Adicionar Inbound",
       "generalActions": "Ações Gerais",
       "generalActions": "Ações Gerais",
       "modifyInbound": "Modificar Inbound",
       "modifyInbound": "Modificar Inbound",
@@ -292,11 +300,29 @@
       "delAllClients": "Excluir todos os clientes",
       "delAllClients": "Excluir todos os clientes",
       "delAllClientsConfirmTitle": "Excluir todos os {count} clientes de \"{remark}\"?",
       "delAllClientsConfirmTitle": "Excluir todos os {count} clientes de \"{remark}\"?",
       "delAllClientsConfirmContent": "Remove todos os clientes deste inbound e descarta seus registros de tráfego. O inbound em si é mantido. Esta ação não pode ser desfeita.",
       "delAllClientsConfirmContent": "Remove todos os clientes deste inbound e descarta seus registros de tráfego. O inbound em si é mantido. Esta ação não pode ser desfeita.",
+      "attachClients": "Associar clientes a…",
+      "addClientsToGroup": "Adicionar clientes ao grupo…",
+      "attachClientsTitle": "Associar clientes de «{remark}»",
+      "attachClientsDesc": "Associa os mesmos {count} cliente(s) (mesmo UUID/senha e tráfego compartilhado) à(s) entrada(s) selecionada(s). Permanecem nesta entrada também.",
+      "attachClientsTargets": "Entradas de destino",
+      "attachClientsNoTargets": "Não há outras entradas compatíveis disponíveis para associação.",
+      "attachClientsResult": "Associados {attached}, ignorados {skipped}.",
+      "attachClientsResultMixed": "Associados {attached}, ignorados {skipped}, erros {errors}.",
+      "attachClientsSelectLabel": "Clientes para associar",
+      "attachClientsSearchPlaceholder": "Buscar email ou comentário",
+      "attachClientsStatusDisabled": "Desabilitado",
+      "attachClientsSelectedCount": "{selected} de {total} selecionado(s)",
+      "detachClients": "Desassociar clientes",
+      "detachClientsTitle": "Desassociar clientes de «{remark}»",
+      "detachClientsDesc": "Remove o(s) cliente(s) selecionado(s) apenas desta entrada. Os registros são mantidos (use Delete para remover completamente). A origem tem {count} cliente(s) no total.",
+      "detachClientsResult": "Desassociados {detached}, ignorados {skipped}.",
+      "detachClientsResultMixed": "Desassociados {detached}, ignorados {skipped}, erros {errors}.",
+      "detachClientsSelectLabel": "Clientes para desassociar",
       "exportLinksTitle": "Exportar links do inbound",
       "exportLinksTitle": "Exportar links do inbound",
       "exportSubsTitle": "Exportar links de assinatura",
       "exportSubsTitle": "Exportar links de assinatura",
       "exportAllLinksTitle": "Exportar todos os links de inbound",
       "exportAllLinksTitle": "Exportar todos os links de inbound",
       "exportAllSubsTitle": "Exportar todos os links de assinatura",
       "exportAllSubsTitle": "Exportar todos os links de assinatura",
-      "inboundJsonTitle": "JSON do inbound",
+      "inboundJsonTitle": "JSON da entrada",
       "deleteClient": "Excluir Cliente",
       "deleteClient": "Excluir Cliente",
       "deleteClientContent": "Tem certeza de que deseja excluir o cliente?",
       "deleteClientContent": "Tem certeza de que deseja excluir o cliente?",
       "resetTrafficContent": "Tem certeza de que deseja redefinir o tráfego?",
       "resetTrafficContent": "Tem certeza de que deseja redefinir o tráfego?",
@@ -341,6 +367,7 @@
       "IPLimitlogDesc": "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)",
       "IPLimitlogDesc": "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)",
       "IPLimitlogclear": "Limpar o Log",
       "IPLimitlogclear": "Limpar o Log",
       "setDefaultCert": "Definir Certificado pelo Painel",
       "setDefaultCert": "Definir Certificado pelo Painel",
+      "setDefaultCertEmpty": "Nenhum certificado configurado para o painel. Configure um em Configurações primeiro.",
       "streamTab": "Stream",
       "streamTab": "Stream",
       "securityTab": "Segurança",
       "securityTab": "Segurança",
       "sniffingTab": "Sniffing",
       "sniffingTab": "Sniffing",
@@ -369,7 +396,6 @@
       },
       },
       "telegramDesc": "Por favor, forneça o ID do Chat do Telegram. (use o comando '/id' no bot) ou ({'@'}userinfobot)",
       "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.",
       "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",
       "same": "Igual",
       "inboundData": "Dados do Inbound",
       "inboundData": "Dados do Inbound",
       "exportInbound": "Exportar Inbound",
       "exportInbound": "Exportar Inbound",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Erro ao obter o certificado mldsa65.",
         "getNewmldsa65Error": "Erro ao obter o certificado mldsa65.",
         "getNewVlessEncError": "Erro ao obter o certificado VlessEnc."
         "getNewVlessEncError": "Erro ao obter o certificado VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Mover para cima",
+        "moveDown": "Mover para baixo",
+        "addAll": "Adicionar todos",
+        "addAllFallbackTooltip": "Adiciona uma linha de fallback para cada entrada elegível ainda não conectada",
+        "peers": "Peers",
+        "addPeer": "Adicionar peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Apenas Windows. CIDRs são adicionados à tabela de roteamento do sistema automaticamente para que o tráfego correspondente passe pelo TUN.",
+        "autoOutboundsInterface": "Interface de saída automática",
+        "autoOutboundsInterfaceTooltip": "Interface física para tráfego de saída. Use 'auto' para detecção; auto-habilitado quando Auto system routes está ativo.",
+        "rewriteAddress": "Reescrever endereço",
+        "rewritePort": "Reescrever porta",
+        "allowedNetwork": "Rede permitida",
+        "followRedirect": "Seguir redirect",
+        "accounts": "Contas",
+        "allowTransparent": "Permitir transparente",
+        "encryptionMethod": "Método de criptografia",
+        "visionTestseed": "Vision testseed",
+        "version": "Versão",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "Masquerade",
+        "type": "Tipo",
+        "upstreamUrl": "URL Upstream",
+        "rewriteHost": "Reescrever Host",
+        "skipTlsVerify": "Pular verificação TLS",
+        "directory": "Diretório",
+        "statusCode": "Código de status",
+        "body": "Body",
+        "headers": "Cabeçalhos",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Versão da requisição",
+        "requestMethod": "Método da requisição",
+        "requestPath": "Caminho da requisição",
+        "requestHeaders": "Cabeçalhos de requisição",
+        "responseVersion": "Versão da resposta",
+        "responseStatus": "Status da resposta",
+        "responseReason": "Motivo da resposta",
+        "responseHeaders": "Cabeçalhos de resposta",
+        "heartbeatPeriod": "Período de heartbeat",
+        "serviceName": "Nome do serviço",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Máx. upload em buffer",
+        "maxUploadSize": "Tamanho máx. de upload (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Máx. bytes cabeçalho servidor",
+        "paddingBytes": "Bytes de Padding",
+        "uplinkHttpMethod": "Método HTTP Uplink",
+        "paddingObfsMode": "Modo obfs de Padding",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Posição de Padding",
+        "paddingMethod": "Método de Padding",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Sem cabeçalho SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Uplink (MB/s)",
+        "downlinkMbps": "Downlink (MB/s)",
+        "cwndMultiplier": "Multiplicador CWND",
+        "maxSendingWindow": "Máx. janela de envio",
+        "externalProxy": "Proxy externo",
+        "sniPlaceholder": "SNI (padrão = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Padrão",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Apenas V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For confiável",
+        "addressPortStrategy": "Estratégia endereço+porta",
+        "tryDelayMs": "Atraso de tentativa (ms)",
+        "prioritizeIPv6": "Priorizar IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Máx. tentativas simultâneas",
+        "customSockopt": "Sockopt personalizado",
+        "addCustomOption": "Adicionar opção personalizada",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Auto",
+        "minMaxVersion": "Versão mín/máx",
+        "rejectUnknownSni": "Rejeitar SNI desconhecido",
+        "disableSystemRoot": "Desabilitar System Root",
+        "sessionResumption": "Retomada de sessão",
+        "oneTimeLoading": "Carregamento único",
+        "usageOption": "Opção de uso",
+        "buildChain": "Construir cadeia",
+        "echKey": "ECH key",
+        "echConfig": "Config ECH",
+        "getNewEchCert": "Obter novo certificado ECH",
+        "show": "Mostrar",
+        "xver": "Xver",
+        "target": "Alvo",
+        "maxTimeDiff": "Máx. diferença de tempo (ms)",
+        "minClientVer": "Mín. versão cliente",
+        "maxClientVer": "Máx. versão cliente",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Obter novo certificado",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Obter novo Seed"
+      },
+      "info": {
+        "mode": "Modo",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Nome da interface",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Interface de saída",
+        "autoSystemRoutes": "Rotas do sistema automáticas",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN sem kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Config Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Requisição",
           "request": "Requisição",
@@ -456,6 +615,20 @@
       "days": "Dia(s)",
       "days": "Dia(s)",
       "renew": "Renovação automática",
       "renew": "Renovação automática",
       "renewDesc": "Renovação automática após a expiração. (0 = desativar) (unidade: dia)",
       "renewDesc": "Renovação automática após a expiração. (0 = desativar) (unidade: dia)",
+      "searchPlaceholder": "Buscar email, comentário, sub ID, UUID, senha, auth…",
+      "filterTitle": "Filtrar clientes",
+      "clearAllFilters": "Limpar tudo",
+      "sortOldest": "Mais antigos primeiro",
+      "sortNewest": "Mais novos primeiro",
+      "sortRecentlyUpdated": "Atualizados recentemente",
+      "sortRecentlyOnline": "Online recentemente",
+      "sortEmailAZ": "Email A→Z",
+      "sortEmailZA": "Email Z→A",
+      "sortMostTraffic": "Mais tráfego",
+      "sortHighestRemaining": "Maior restante",
+      "sortExpiringSoonest": "Expira em breve",
+      "has": "Tem",
+      "hasNot": "Não tem",
       "title": "Clientes",
       "title": "Clientes",
       "actions": "Ações",
       "actions": "Ações",
       "totalGB": "Total enviado/recebido (GB)",
       "totalGB": "Total enviado/recebido (GB)",
@@ -465,7 +638,10 @@
       "password": "Senha",
       "password": "Senha",
       "subId": "ID da assinatura",
       "subId": "ID da assinatura",
       "online": "Online",
       "online": "Online",
-      "email": "E-mail",
+      "email": "Email",
+      "group": "Grupo",
+      "groupDesc": "Rótulo lógico para agrupar clientes relacionados (ex.: equipe, cliente, região). Filtrável pela barra de ferramentas.",
+      "groupPlaceholder": "ex.: customer-a",
       "comment": "Comentário",
       "comment": "Comentário",
       "traffic": "Tráfego",
       "traffic": "Tráfego",
       "offline": "Offline",
       "offline": "Offline",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Redefinir o tráfego de todos os clientes",
       "resetAllTraffics": "Redefinir o tráfego de todos os clientes",
       "resetAllTrafficsTitle": "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.",
       "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}?",
       "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.",
       "deleteConfirmContent": "Isto remove o cliente de cada inbound associado e descarta o registro de tráfego. Não é possível desfazer.",
       "deleteSelected": "Excluir ({count})",
       "deleteSelected": "Excluir ({count})",
       "adjustSelected": "Ajustar ({count})",
       "adjustSelected": "Ajustar ({count})",
+      "subLinksSelected": "Links sub ({count})",
+      "addToGroupTitle": "Adicionar {count} cliente(s) a um grupo",
+      "addToGroupTooltip": "Escolha um grupo existente ou digite um novo nome. Use Ungroup para remover clientes do grupo atual.",
+      "addToGroupPlaceholder": "Nome do grupo",
+      "addToGroupSuccessToast": "{count} cliente(s) adicionado(s) a {group}",
+      "ungroupSuccessToast": "Grupo limpo de {count} cliente(s)",
+      "ungroup": "Desagrupar",
+      "ungroupConfirmTitle": "Remover {count} cliente(s) do grupo?",
+      "ungroupConfirmContent": "Limpa o rótulo de grupo de cada cliente selecionado. Os clientes em si são mantidos (use Delete para remover completamente).",
+      "addToGroup": "Adicionar ao grupo",
+      "attach": "Associar",
+      "adjust": "Ajustar",
+      "subLinks": "Links de assinatura",
+      "selectedCount": "{count} selecionado(s)",
+      "attachSelected": "Associar ({count})",
+      "attachToInboundsTitle": "Associar {count} cliente(s) a entrada(s)",
+      "attachToInboundsDesc": "Associa os {count} cliente(s) selecionados (mesmo UUID/senha e tráfego compartilhado) às entradas escolhidas. Mantêm suas associações existentes.",
+      "attachToInboundsTargets": "Entradas de destino",
+      "attachToInboundsNoTargets": "Não há entradas multiusuário disponíveis para associação.",
+      "detachSelected": "Desassociar ({count})",
+      "detach": "Desassociar",
+      "detachFromInboundsTitle": "Desassociar {count} cliente(s) de entrada(s)",
+      "detachFromInboundsDesc": "Remove os {count} cliente(s) selecionados das entradas escolhidas. Pares onde o cliente não estava associado são ignorados silenciosamente. Os registros dos clientes são mantidos (use Delete para remover completamente).",
+      "detachFromInboundsTargets": "Entradas para desassociar",
+      "detachFromInboundsNoTargets": "Não há entradas multiusuário disponíveis.",
+      "detachFromInboundsResult": "Desassociados {detached}, ignorados {skipped}.",
+      "detachFromInboundsResultMixed": "Desassociados {detached}, ignorados {skipped}, erros {errors}.",
+      "subLinksTitle": "Links sub ({count})",
+      "subLinkColumn": "URL da assinatura",
+      "subJsonLinkColumn": "URL JSON da assinatura",
+      "subLinksCopyAll": "Copiar tudo",
+      "subLinksCopiedAll": "Copiados {count} link(s)",
+      "subLinksEmpty": "Nenhum dos clientes selecionados tem ID de assinatura.",
+      "subLinksDisabled": "O serviço de assinatura está desabilitado.",
+      "subLinksDisabledHint": "Habilite a assinatura em Configurações do Painel → Assinatura para gerar links.",
       "bulkDeleteConfirmTitle": "Excluir {count} clientes?",
       "bulkDeleteConfirmTitle": "Excluir {count} clientes?",
       "bulkDeleteConfirmContent": "Cada cliente selecionado é removido dos inbounds associados e o registro de tráfego é descartado. Não é possível desfazer.",
       "bulkDeleteConfirmContent": "Cada cliente selecionado é removido dos inbounds associados e o registro de tráfego é descartado. Não é possível desfazer.",
       "bulkAdjustTitle": "Ajustar {count} clientes",
       "bulkAdjustTitle": "Ajustar {count} clientes",
@@ -505,10 +715,11 @@
       "delDepletedConfirmTitle": "Excluir clientes 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.",
       "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",
       "auth": "Auth",
-      "hysteriaAuth": "Auth do Hysteria",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "Segurança VMess",
+      "reverseTag": "Tag reversa",
       "reverseTagPlaceholder": "Reverse tag opcional",
       "reverseTagPlaceholder": "Reverse tag opcional",
       "telegramId": "ID de usuário do Telegram",
       "telegramId": "ID de usuário do Telegram",
       "telegramIdPlaceholder": "ID numérico de usuário do Telegram (0 = nenhum)",
       "telegramIdPlaceholder": "ID numérico de usuário do Telegram (0 = nenhum)",
@@ -528,6 +739,44 @@
         "delDepleted": "{count} clientes esgotados excluídos"
         "delDepleted": "{count} clientes esgotados excluídos"
       }
       }
     },
     },
+    "groups": {
+      "title": "Grupos",
+      "name": "Nome",
+      "clientCount": "Clientes no grupo",
+      "totalGroups": "Total de grupos",
+      "totalGroupedClients": "Clientes com grupo",
+      "emptyGroups": "Grupos vazios",
+      "addGroup": "Adicionar grupo",
+      "createSuccess": "Grupo «{name}» criado.",
+      "rename": "Renomear",
+      "renameTitle": "Renomear {name}",
+      "renameCollision": "Já existe um grupo chamado «{name}».",
+      "renameSuccess": "Grupo renomeado em {count} cliente(s).",
+      "deleteConfirmTitle": "Excluir o grupo {name}?",
+      "deleteConfirmContent": "Isso remove o grupo e limpa seu rótulo de {count} cliente(s). Os clientes em si não são excluídos.",
+      "deleteSuccess": "Grupo limpo de {count} cliente(s).",
+      "resetTraffic": "Redefinir tráfego",
+      "resetConfirmTitle": "Redefinir tráfego do grupo {name}?",
+      "resetConfirmContent": "Isso zera up/down para todos os {count} cliente(s) deste grupo.",
+      "resetSuccess": "Tráfego redefinido para {count} cliente(s).",
+      "adjustSuccess": "Ajustados {count} cliente(s) em {name}.",
+      "emptyForAction": "Este grupo ainda não tem clientes.",
+      "deleteGroupOnly": "Excluir grupo (manter clientes)",
+      "deleteClients": "Excluir clientes do grupo",
+      "deleteClientsConfirmTitle": "Excluir todos os clientes em {name}?",
+      "deleteClientsConfirmContent": "Isso remove permanentemente {count} cliente(s) junto com seus registros de tráfego. O rótulo de grupo também é limpo. Isso não pode ser desfeito.",
+      "deleteClientsSuccess": "Excluídos {count} cliente(s).",
+      "deleteClientsMixed": "{ok} excluídos, {failed} ignorados",
+      "addToGroup": "Adicionar clientes…",
+      "addToGroupTitle": "Adicionar clientes ao grupo «{name}»",
+      "addToGroupDesc": "Selecione clientes para adicionar a este grupo. Mantêm suas associações de entrada atuais; apenas o rótulo de grupo muda. Clientes já neste grupo não são listados.",
+      "addToGroupEmpty": "Não há outros clientes disponíveis para adicionar.",
+      "addToGroupResult": "Adicionados {count} cliente(s) a {name}.",
+      "removeFromGroup": "Remover clientes…",
+      "removeFromGroupTitle": "Remover clientes do grupo «{name}»",
+      "removeFromGroupDesc": "Selecione membros para remover deste grupo. Os clientes em si são mantidos (use «Excluir clientes do grupo» para removê-los por completo).",
+      "removeFromGroupResult": "Removidos {count} cliente(s) de {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Nós",
       "title": "Nós",
       "addNode": "Adicionar nó",
       "addNode": "Adicionar nó",
@@ -544,7 +793,7 @@
       "address": "Endereço",
       "address": "Endereço",
       "port": "Porta",
       "port": "Porta",
       "basePath": "Caminho base",
       "basePath": "Caminho base",
-      "apiToken": "Token da API",
+      "apiToken": "Token API",
       "apiTokenPlaceholder": "Token da página de Configurações do painel remoto",
       "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.",
       "apiTokenHint": "O painel remoto exibe o token da API em Configurações → Token da API.",
       "regenerate": "Regenerar token",
       "regenerate": "Regenerar token",
@@ -590,7 +839,7 @@
       "title": "Configurações do Painel",
       "title": "Configurações do Painel",
       "save": "Salvar",
       "save": "Salvar",
       "infoDesc": "Toda alteração feita aqui precisa ser salva. Reinicie o painel para aplicar as alterações.",
       "infoDesc": "Toda alteração feita aqui precisa ser salva. Reinicie o painel para aplicar as alterações.",
-      "restartPanel": "Reiniciar Painel",
+      "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.",
       "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",
       "restartPanelSuccess": "O painel foi reiniciado com sucesso",
       "actions": "Ações",
       "actions": "Ações",
@@ -619,6 +868,8 @@
       "panelUrlPathDesc": "O caminho URI para o painel web. (começa com ‘/‘ e termina com ‘/‘)",
       "panelUrlPathDesc": "O caminho URI para o painel web. (começa com ‘/‘ e termina com ‘/‘)",
       "pageSize": "Tamanho da Paginação",
       "pageSize": "Tamanho da Paginação",
       "pageSizeDesc": "Definir o tamanho da página para a tabela de entradas. (0 = desativado)",
       "pageSizeDesc": "Definir o tamanho da página para a tabela de entradas. (0 = desativado)",
+      "panelProxy": "Proxy de rede do painel",
+      "panelProxyDesc": "Encaminha as requisições de saída do próprio painel (atualizações de geo, verificações de versão do Xray/painel, Telegram) por este proxy para contornar a filtragem de GitHub/Telegram no servidor. Aceita socks5:// ou http(s)://, ex. uma entrada SOCKS local do Xray. Deixe vazio para conexão direta.",
       "remarkModel": "Modelo de Observação & Caractere de Separação",
       "remarkModel": "Modelo de Observação & Caractere de Separação",
       "datepicker": "Tipo de Calendário",
       "datepicker": "Tipo de Calendário",
       "datepickerPlaceholder": "Selecionar data",
       "datepickerPlaceholder": "Selecionar data",
@@ -634,7 +885,7 @@
       "telegramTokenDesc": "O token do bot do Telegram obtido de '{'@'}BotFather'.",
       "telegramTokenDesc": "O token do bot do Telegram obtido de '{'@'}BotFather'.",
       "telegramProxy": "Proxy SOCKS",
       "telegramProxy": "Proxy SOCKS",
       "telegramProxyDesc": "Ativa o proxy SOCKS5 para conectar ao Telegram. (ajuste as configurações conforme o guia)",
       "telegramProxyDesc": "Ativa o proxy SOCKS5 para conectar ao Telegram. (ajuste as configurações conforme o guia)",
-      "telegramAPIServer": "API Server do Telegram",
+      "telegramAPIServer": "Servidor API do Telegram",
       "telegramAPIServerDesc": "O servidor API do Telegram a ser usado. Deixe em branco para usar o servidor padrão.",
       "telegramAPIServerDesc": "O servidor API do Telegram a ser usado. Deixe em branco para usar o servidor padrão.",
       "telegramChatId": "ID de Chat do Administrador",
       "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)",
       "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)",
@@ -658,6 +909,8 @@
       "subEnable": "Ativar Serviço de Assinatura",
       "subEnable": "Ativar Serviço de Assinatura",
       "subEnableDesc": "Ativa o serviço de assinatura.",
       "subEnableDesc": "Ativa o serviço de assinatura.",
       "subJsonEnable": "Ativar/Desativar o endpoint de assinatura JSON de forma independente.",
       "subJsonEnable": "Ativar/Desativar o endpoint de assinatura JSON de forma independente.",
+      "subJsonEnableTitle": "Assinatura JSON",
+      "subClashEnableTitle": "Assinatura Clash / Mihomo",
       "subTitle": "Título da Assinatura",
       "subTitle": "Título da Assinatura",
       "subTitleDesc": "Título exibido no cliente VPN",
       "subTitleDesc": "Título exibido no cliente VPN",
       "subSupportUrl": "URL de Suporte",
       "subSupportUrl": "URL de Suporte",
@@ -693,7 +946,7 @@
       "subURI": "URI de Proxy Reverso",
       "subURI": "URI de Proxy Reverso",
       "subURIDesc": "O caminho URI da URL de assinatura para uso por trás de proxies.",
       "subURIDesc": "O caminho URI da URL de assinatura para uso por trás de proxies.",
       "externalTrafficInformEnable": "Informações de tráfego externo",
       "externalTrafficInformEnable": "Informações de tráfego externo",
-      "externalTrafficInformEnableDesc": "Informar a API externa sobre cada atualização de tráfego.",
+      "externalTrafficInformEnableDesc": "Informar API externa a cada atualização de tráfego.",
       "externalTrafficInformURI": "URI de informação de tráfego externo",
       "externalTrafficInformURI": "URI de informação de tráfego externo",
       "externalTrafficInformURIDesc": "As atualizações de tráfego são enviadas para este URI.",
       "externalTrafficInformURIDesc": "As atualizações de tráfego são enviadas para este URI.",
       "restartXrayOnClientDisable": "Reiniciar Xray Após Desativação Automática",
       "restartXrayOnClientDisable": "Reiniciar Xray Após Desativação Automática",
@@ -703,6 +956,54 @@
       "fragmentSett": "Configurações de Fragmentação",
       "fragmentSett": "Configurações de Fragmentação",
       "noisesDesc": "Ativar Noises.",
       "noisesDesc": "Ativar Noises.",
       "noisesSett": "Configurações de Noises",
       "noisesSett": "Configurações de Noises",
+      "trustedProxyCidrs": "CIDRs de proxy confiável",
+      "trustedProxyCidrsDesc": "IPs/CIDRs separados por vírgula que podem definir os cabeçalhos host, proto e IP do cliente encaminhados.",
+      "ldap": {
+        "enable": "Habilitar sincronização LDAP",
+        "host": "Host LDAP",
+        "port": "Porta LDAP",
+        "useTls": "Usar TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Configurada; deixe em branco para manter a senha atual.",
+        "passwordUnconfigured": "Não configurada.",
+        "passwordPlaceholder": "Configurada — digite um novo valor para substituir",
+        "baseDn": "Base DN",
+        "userFilter": "Filtro de usuário",
+        "userAttr": "Atributo de usuário (username/email)",
+        "vlessField": "Atributo flag VLESS",
+        "flagField": "Atributo flag genérico (opcional)",
+        "flagFieldDesc": "Se definido, sobrescreve o flag VLESS — ex. shadowInactive.",
+        "truthyValues": "Valores truthy",
+        "truthyValuesDesc": "Separados por vírgula; padrão: true,1,yes,on",
+        "invertFlag": "Inverter flag",
+        "invertFlagDesc": "Habilite quando o atributo significar «desabilitado» (ex. shadowInactive).",
+        "syncSchedule": "Agendamento da sincronização",
+        "syncScheduleDesc": "String tipo cron, ex. @every 1m",
+        "inboundTags": "Tags de entradas",
+        "inboundTagsDesc": "Entradas nas quais a sincronização LDAP pode auto-criar ou auto-excluir clientes.",
+        "noInbounds": "Nenhuma entrada encontrada. Crie uma em Entradas primeiro.",
+        "autoCreate": "Criar clientes automaticamente",
+        "autoDelete": "Excluir clientes automaticamente",
+        "defaultTotalGb": "Total padrão (GB)",
+        "defaultExpiryDays": "Expiração padrão (dias)",
+        "defaultIpLimit": "Limite de IP padrão"
+      },
+      "subFormats": {
+        "packets": "Pacotes",
+        "length": "Comprimento",
+        "interval": "Intervalo",
+        "maxSplit": "Máx. divisão",
+        "noises": "Ruídos",
+        "noiseItem": "Ruído №{n}",
+        "type": "Tipo",
+        "packet": "Pacote",
+        "delayMs": "Atraso (ms)",
+        "applyTo": "Aplicar a",
+        "addNoise": "+ Ruído",
+        "concurrency": "Concorrência",
+        "xudpConcurrency": "Concorrência xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido.",
       "muxDesc": "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido.",
       "muxSett": "Configurações de Mux",
       "muxSett": "Configurações de Mux",
@@ -758,6 +1059,9 @@
       "save": "Salvar",
       "save": "Salvar",
       "restart": "Reiniciar Xray",
       "restart": "Reiniciar Xray",
       "restartSuccess": "Xray foi reiniciado com sucesso",
       "restartSuccess": "Xray foi reiniciado com sucesso",
+      "restartOutputTitle": "Saída do reinício do Xray",
+      "restartConfirmTitle": "Reiniciar xray?",
+      "restartConfirmContent": "Recarrega o serviço xray com a configuração salva.",
       "stopSuccess": "Xray foi interrompido com sucesso",
       "stopSuccess": "Xray foi interrompido com sucesso",
       "restartError": "Ocorreu um erro ao reiniciar o Xray.",
       "restartError": "Ocorreu um erro ao reiniciar o Xray.",
       "stopError": "Ocorreu um erro ao parar o Xray.",
       "stopError": "Ocorreu um erro ao parar o Xray.",
@@ -790,14 +1094,16 @@
       "outboundTestUrl": "URL de teste de outbound",
       "outboundTestUrl": "URL de teste de outbound",
       "outboundTestUrlDesc": "URL usada ao testar conectividade do outbound",
       "outboundTestUrlDesc": "URL usada ao testar conectividade do outbound",
       "Torrent": "Bloquear Protocolo BitTorrent",
       "Torrent": "Bloquear Protocolo BitTorrent",
-      "Inbounds": "Inbounds",
+      "Inbounds": "Entradas",
       "InboundsDesc": "Aceitar clientes específicos.",
       "InboundsDesc": "Aceitar clientes específicos.",
-      "Outbounds": "Outbounds",
+      "Outbounds": "Saídas",
       "Balancers": "Balanceadores",
       "Balancers": "Balanceadores",
+      "balancerTagRequired": "A tag é obrigatória",
+      "balancerSelectorRequired": "Selecione pelo menos uma saída",
       "OutboundsDesc": "Definir o caminho de saída do tráfego.",
       "OutboundsDesc": "Definir o caminho de saída do tráfego.",
       "Routings": "Regras de Roteamento",
       "Routings": "Regras de Roteamento",
       "RoutingsDesc": "A prioridade de cada regra é importante!",
       "RoutingsDesc": "A prioridade de cada regra é importante!",
-      "completeTemplate": "Todos",
+      "completeTemplate": "Tudo",
       "logLevel": "Nível de Log",
       "logLevel": "Nível de Log",
       "logLevelDesc": "O nível de log para erros, indicando a informação que precisa ser registrada.",
       "logLevelDesc": "O nível de log para erros, indicando a informação que precisa ser registrada.",
       "accessLog": "Log de Acesso",
       "accessLog": "Log de Acesso",
@@ -832,6 +1138,73 @@
         "edit": "Editar Regra",
         "edit": "Editar Regra",
         "useComma": "Itens separados por vírgula"
         "useComma": "Itens separados por vírgula"
       },
       },
+      "routing": {
+        "dragToReorder": "Arraste para reordenar"
+      },
+      "ruleForm": {
+        "sourceIps": "IPs de origem",
+        "sourcePort": "Porta de origem",
+        "vlessRoute": "Rota VLESS",
+        "attributes": "Atributos",
+        "value": "Valor",
+        "user": "Usuário",
+        "inboundTags": "Tags de entradas",
+        "outboundTag": "Tag de saída",
+        "balancerTag": "Tag de balanceador",
+        "balancerTagTooltip": "Encaminha tráfego por um dos balanceadores configurados"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Tag já usada por outra saída",
+        "tagRequired": "A tag é obrigatória",
+        "tagPlaceholder": "tag-única",
+        "localIpPlaceholder": "IP local",
+        "addressRequired": "Endereço é obrigatório",
+        "portRequired": "Porta é obrigatória",
+        "optional": "opcional",
+        "udpOverTcp": "UDP sobre TCP",
+        "uotVersion": "Versão UoT",
+        "inboundTag": "Tag de entrada",
+        "inboundTagPlaceholder": "tag de entrada usada em regras de roteamento",
+        "responseType": "Tipo de resposta",
+        "rewriteNetwork": "Reescrever rede",
+        "unchanged": "(inalterado)",
+        "unchangedAddress": "(inalterado) ex. 1.1.1.1",
+        "rules": "Regras",
+        "ruleN": "Regra {n}",
+        "action": "Ação",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Regras finais",
+        "overrideXrayPrivateIp": "Sobrescrever o bloqueio de IP privado padrão do Xray",
+        "blockDelay": "Atraso do bloqueio (ms)",
+        "reverseSniffing": "Sniffing reverso",
+        "workers": "Workers",
+        "reserved": "Reservado",
+        "minUploadInterval": "Intervalo mín. de upload (ms)",
+        "maxUploadSizeBytes": "Tamanho máx. de upload (bytes)",
+        "uplinkChunkSize": "Tamanho do chunk Uplink",
+        "noGrpcHeader": "Sem cabeçalho gRPC",
+        "maxConcurrency": "Máx. concorrência",
+        "maxConnections": "Máx. conexões",
+        "maxReuseTimes": "Máx. reutilizações",
+        "maxRequestTimes": "Máx. requisições",
+        "maxReusableSecs": "Máx. segundos reutilizáveis",
+        "keepAlivePeriod": "Período keep alive",
+        "authPassword": "Senha de auth",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "nome do servidor",
+        "verifyPeerName": "Verificar nome do peer",
+        "pinnedSha256": "SHA256 pinned",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Intervalo keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Interface",
+        "ipv6Only": "Apenas IPv6",
+        "acceptProxyProtocol": "Aceitar proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Adicionar Saída",
         "addOutbound": "Adicionar Saída",
         "addReverse": "Adicionar Reverso",
         "addReverse": "Adicionar Reverso",
@@ -846,7 +1219,7 @@
         "reverse": "Reverso",
         "reverse": "Reverso",
         "domain": "Domínio",
         "domain": "Domínio",
         "type": "Tipo",
         "type": "Tipo",
-        "bridge": "Ponte",
+        "bridge": "Bridge",
         "portal": "Portal",
         "portal": "Portal",
         "link": "Link",
         "link": "Link",
         "intercon": "Interconexão",
         "intercon": "Interconexão",
@@ -860,6 +1233,8 @@
         "testSuccess": "Teste bem-sucedido",
         "testSuccess": "Teste bem-sucedido",
         "testFailed": "Teste falhou",
         "testFailed": "Teste falhou",
         "testError": "Falha ao testar saída",
         "testError": "Falha ao testar saída",
+        "testModeTooltip": "TCP: sondagem rápida apenas de dial. HTTP: requisição completa pelo xray.",
+        "testAll": "Testar todos",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Token de Acesso",
         "accessToken": "Token de Acesso",
         "country": "País",
         "country": "País",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "Seletores",
         "balancerSelectors": "Seletores",
         "tag": "Tag",
         "tag": "Tag",
         "tagDesc": "Tag Única",
         "tagDesc": "Tag Única",
+        "tagDuplicate": "Tag já usada por outro balanceador",
+        "tagPlaceholder": "tag única do balanceador",
+        "selector": "Seletor",
+        "fallback": "Fallback",
+        "expected": "Esperado",
+        "expectedPlaceholder": "número ótimo de nós",
+        "maxRtt": "Máx. RTT",
+        "tolerance": "Tolerância",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "Não é possível usar balancerTag e outboundTag ao mesmo tempo. Se usados simultaneamente, apenas outboundTag funcionará."
         "balancerDesc": "Não é possível usar balancerTag e outboundTag ao mesmo tempo. Se usados simultaneamente, apenas outboundTag funcionará."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Nível do Usuário",
         "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"
         "userLevelDesc": "Todas as conexões feitas através deste inbound usarão este nível de usuário. O padrão é 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Chave privada",
+        "noServers": "Nenhum servidor encontrado para o país selecionado",
+        "noPublicKey": "O servidor selecionado não anuncia uma chave pública NordLynx.",
+        "outboundAdded": "Saída NordVPN adicionada",
+        "outboundUpdated": "Saída NordVPN atualizada"
+      },
+      "warp": {
+        "licenseError": "Falha ao definir licença WARP.",
+        "fetchFirst": "Obtenha primeiro a configuração WARP.",
+        "createAccount": "Criar conta WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID do dispositivo",
+        "licenseKey": "Chave de licença",
+        "privateKey": "Chave privada",
+        "deleteAccount": "Excluir conta",
+        "settings": "Configurações",
+        "licenseKeyLabel": "Chave de licença WARP / WARP+",
+        "key": "Chave",
+        "keyPlaceholder": "chave WARP+ de 26 caracteres",
+        "accountInfo": "Informação da conta",
+        "deviceName": "Nome do dispositivo",
+        "deviceModel": "Modelo do dispositivo",
+        "deviceEnabled": "Dispositivo habilitado",
+        "accountType": "Tipo de conta",
+        "role": "Função",
+        "warpPlusData": "Dados WARP+",
+        "quota": "Quota",
+        "usage": "Uso",
+        "addOutbound": "Adicionar saída"
+      },
       "dns": {
       "dns": {
         "enable": "Ativar DNS",
         "enable": "Ativar DNS",
         "enableDesc": "Ativar o servidor DNS integrado",
         "enableDesc": "Ativar o servidor DNS integrado",
@@ -959,7 +1376,7 @@
     "hours": "Horas",
     "hours": "Horas",
     "minutes": "Minutos",
     "minutes": "Minutos",
     "unknown": "Desconhecido",
     "unknown": "Desconhecido",
-    "inbounds": "Inbounds",
+    "inbounds": "Entradas",
     "clients": "Clientes",
     "clients": "Clientes",
     "offline": "🔴 Offline",
     "offline": "🔴 Offline",
     "online": "🟢 Online",
     "online": "🟢 Online",
@@ -1009,7 +1426,7 @@
       "username": "👤 Nome de usuário: {{ .Username }}\r\n",
       "username": "👤 Nome de usuário: {{ .Username }}\r\n",
       "reason": "❗️ Motivo: {{ .Reason }}\r\n",
       "reason": "❗️ Motivo: {{ .Reason }}\r\n",
       "time": "⏰ Hora: {{ .Time }}\r\n",
       "time": "⏰ Hora: {{ .Time }}\r\n",
-      "inbound": "📍 Inbound: {{ .Remark }}\r\n",
+      "inbound": "📍 Entrada: {{ .Remark }}\r\n",
       "port": "🔌 Porta: {{ .Port }}\r\n",
       "port": "🔌 Porta: {{ .Port }}\r\n",
       "expire": "📅 Data de expiração: {{ .Time }}\r\n",
       "expire": "📅 Data de expiração: {{ .Time }}\r\n",
       "expireIn": "📅 Expira em: {{ .Time }}\r\n",
       "expireIn": "📅 Expira em: {{ .Time }}\r\n",
@@ -1089,9 +1506,9 @@
       "use_default": "🏷️ Usar padrão",
       "use_default": "🏷️ Usar padrão",
       "change_id": "⚙️🔑 ID",
       "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 Senha",
       "change_password": "⚙️🔑 Senha",
-      "change_email": "⚙️📧 E-mail",
+      "change_email": "⚙️📧 Email",
       "change_comment": "⚙️💬 Comentário",
       "change_comment": "⚙️💬 Comentário",
-      "change_flow": "⚙️🚦 Fluxo",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "Redefinir Todo o Tráfego",
       "ResetAllTraffics": "Redefinir Todo o Tráfego",
       "SortedTrafficUsageReport": "Relatório de Uso de Tráfego Ordenado"
       "SortedTrafficUsageReport": "Relatório de Uso de Tráfego Ordenado"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Escolha um Inbound"
       "chooseInbound": "Escolha um Inbound"
     }
     }
   }
   }
-}
+}

+ 487 - 70
web/translation/ru-RU.json

@@ -8,15 +8,22 @@
   "save": "Сохранить",
   "save": "Сохранить",
   "logout": "Выход",
   "logout": "Выход",
   "create": "Создать",
   "create": "Создать",
+  "add": "Добавить",
+  "remove": "Удалить",
   "update": "Обновить",
   "update": "Обновить",
   "copy": "Копировать",
   "copy": "Копировать",
   "copied": "Скопировано",
   "copied": "Скопировано",
+  "more": "ещё",
   "download": "Скачать",
   "download": "Скачать",
   "remark": "Примечание",
   "remark": "Примечание",
   "enable": "Включить",
   "enable": "Включить",
   "protocol": "Протокол",
   "protocol": "Протокол",
   "search": "Поиск",
   "search": "Поиск",
   "filter": "Фильтр",
   "filter": "Фильтр",
+  "all": "Все",
+  "from": "От",
+  "to": "До",
+  "done": "Готово",
   "loading": "Загрузка...",
   "loading": "Загрузка...",
   "refresh": "Обновить",
   "refresh": "Обновить",
   "clear": "Очистить",
   "clear": "Очистить",
@@ -27,12 +34,12 @@
   "check": "Проверить",
   "check": "Проверить",
   "indefinite": "Бесконечно",
   "indefinite": "Бесконечно",
   "unlimited": "Безлимит",
   "unlimited": "Безлимит",
-  "none": "Пусто",
+  "none": "Нет",
   "qrCode": "QR-код",
   "qrCode": "QR-код",
   "info": "Информация",
   "info": "Информация",
   "edit": "Изменить",
   "edit": "Изменить",
   "delete": "Удалить",
   "delete": "Удалить",
-  "reset": "Сбросить",
+  "reset": "Сброс",
   "noData": "Нет данных.",
   "noData": "Нет данных.",
   "copySuccess": "Скопировано",
   "copySuccess": "Скопировано",
   "sure": "Да",
   "sure": "Да",
@@ -41,14 +48,14 @@
   "transmission": "Транспорт",
   "transmission": "Транспорт",
   "host": "Хост",
   "host": "Хост",
   "path": "Путь",
   "path": "Путь",
-  "camouflage": "Маскировка",
+  "camouflage": "Обфускация",
   "status": "Статус",
   "status": "Статус",
   "enabled": "Включено",
   "enabled": "Включено",
   "disabled": "Отключено",
   "disabled": "Отключено",
   "depleted": "Исчерпано",
   "depleted": "Исчерпано",
   "depletingSoon": "Почти исчерпано",
   "depletingSoon": "Почти исчерпано",
-  "offline": "Офлайн",
-  "online": "Онлайн",
+  "offline": "Не в сети",
+  "online": "В сети",
   "domainName": "Домен",
   "domainName": "Домен",
   "monitor": "Мониторинг IP",
   "monitor": "Мониторинг IP",
   "certificate": "SSL-сертификат",
   "certificate": "SSL-сертификат",
@@ -95,11 +102,12 @@
     "dark": "Темная",
     "dark": "Темная",
     "ultraDark": "Очень темная",
     "ultraDark": "Очень темная",
     "dashboard": "Дашборд",
     "dashboard": "Дашборд",
-    "inbounds": "Подключения",
+    "inbounds": "Входящие",
     "clients": "Клиенты",
     "clients": "Клиенты",
+    "groups": "Группы",
     "nodes": "Узлы",
     "nodes": "Узлы",
-    "settings": "Настройки",
-    "xray": "Настройки Xray",
+    "settings": "Настройки панели",
+    "xray": "Конфигурации Xray",
     "apiDocs": "Документация API",
     "apiDocs": "Документация API",
     "logout": "Выход",
     "logout": "Выход",
     "link": "Управление",
     "link": "Управление",
@@ -120,16 +128,16 @@
     },
     },
     "index": {
     "index": {
       "title": "Дашборд",
       "title": "Дашборд",
-      "cpu": "ЦП",
+      "cpu": "CPU",
       "logicalProcessors": "Логические процессоры",
       "logicalProcessors": "Логические процессоры",
       "frequency": "Частота",
       "frequency": "Частота",
-      "swap": "Файл подкачки",
+      "swap": "Swap",
       "storage": "Диск",
       "storage": "Диск",
-      "memory": "ОЗУ",
+      "memory": "RAM",
       "threads": "Потоки",
       "threads": "Потоки",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
-      "stopXray": "Остановить",
-      "restartXray": "Перезапустить",
+      "stopXray": "Стоп",
+      "restartXray": "Перезапуск",
       "xraySwitch": "Выбор версии",
       "xraySwitch": "Выбор версии",
       "xrayUpdates": "Обновления Xray",
       "xrayUpdates": "Обновления Xray",
       "xraySwitchClick": "Выберите нужную версию",
       "xraySwitchClick": "Выберите нужную версию",
@@ -165,8 +173,8 @@
       "ipAddresses": "IP-адреса сервера",
       "ipAddresses": "IP-адреса сервера",
       "toggleIpVisibility": "Скрыть или показать IP-адреса сервера",
       "toggleIpVisibility": "Скрыть или показать IP-адреса сервера",
       "overallSpeed": "Общая скорость передачи трафика",
       "overallSpeed": "Общая скорость передачи трафика",
-      "upload": "Отправка",
-      "download": "Загрузка",
+      "upload": "Загрузка",
+      "download": "Скачать",
       "totalData": "Общий объем трафика",
       "totalData": "Общий объем трафика",
       "sent": "Отправлено",
       "sent": "Отправлено",
       "received": "Получено",
       "received": "Получено",
@@ -226,7 +234,7 @@
       "customGeoErrUpdateAllIncomplete": "Не удалось обновить один или несколько пользовательских источников",
       "customGeoErrUpdateAllIncomplete": "Не удалось обновить один или несколько пользовательских источников",
       "customGeoEmpty": "Пользовательских источников geo пока нет — нажмите «Добавить», чтобы создать",
       "customGeoEmpty": "Пользовательских источников geo пока нет — нажмите «Добавить», чтобы создать",
       "dontRefresh": "Установка в процессе. Не обновляйте страницу",
       "dontRefresh": "Установка в процессе. Не обновляйте страницу",
-      "logs": "Журнал",
+      "logs": "Логи",
       "config": "Конфигурация",
       "config": "Конфигурация",
       "backup": "Резервная копия",
       "backup": "Резервная копия",
       "backupTitle": "Бэкап и восстановление",
       "backupTitle": "Бэкап и восстановление",
@@ -241,7 +249,7 @@
       "getConfigError": "Произошла ошибка при получении конфигурационного файла"
       "getConfigError": "Произошла ошибка при получении конфигурационного файла"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "Подключения",
+      "title": "Входящие",
       "totalDownUp": "Отправлено/получено",
       "totalDownUp": "Отправлено/получено",
       "totalUsage": "Всего трафика",
       "totalUsage": "Всего трафика",
       "inboundCount": "Всего подключений",
       "inboundCount": "Всего подключений",
@@ -252,7 +260,7 @@
       "deployTo": "Развернуть на",
       "deployTo": "Развернуть на",
       "localPanel": "Локальная панель",
       "localPanel": "Локальная панель",
       "fallbacks": {
       "fallbacks": {
-        "title": "Фолбэки",
+        "title": "Fallback'и",
         "help": "Когда соединение на этом инбаунде не совпадает ни с одним клиентом, оно перенаправляется на другой инбаунд. Выберите дочерний инбаунд ниже — поля маршрутизации (SNI / ALPN / Path / xver) заполнятся автоматически из его транспорта, для большинства конфигураций больше ничего менять не нужно. Каждый дочерний должен слушать на 127.0.0.1 с security=none.",
         "help": "Когда соединение на этом инбаунде не совпадает ни с одним клиентом, оно перенаправляется на другой инбаунд. Выберите дочерний инбаунд ниже — поля маршрутизации (SNI / ALPN / Path / xver) заполнятся автоматически из его транспорта, для большинства конфигураций больше ничего менять не нужно. Каждый дочерний должен слушать на 127.0.0.1 с security=none.",
         "empty": "Фолбэков пока нет",
         "empty": "Фолбэков пока нет",
         "add": "Добавить фолбэк",
         "add": "Добавить фолбэк",
@@ -270,14 +278,14 @@
       },
       },
       "protocol": "Протокол",
       "protocol": "Протокол",
       "port": "Порт",
       "port": "Порт",
-      "portMap": "Порт-маппинг",
+      "portMap": "Сопоставление портов",
       "traffic": "Трафик",
       "traffic": "Трафик",
       "details": "Подробнее",
       "details": "Подробнее",
       "transportConfig": "Транспорт",
       "transportConfig": "Транспорт",
       "expireDate": "Дата окончания",
       "expireDate": "Дата окончания",
       "createdAt": "Создано",
       "createdAt": "Создано",
       "updatedAt": "Обновлено",
       "updatedAt": "Обновлено",
-      "resetTraffic": "Сброс трафика",
+      "resetTraffic": "Сбросить трафик",
       "addInbound": "Создать подключение",
       "addInbound": "Создать подключение",
       "generalActions": "Общие действия",
       "generalActions": "Общие действия",
       "modifyInbound": "Изменить подключение",
       "modifyInbound": "Изменить подключение",
@@ -292,11 +300,29 @@
       "delAllClients": "Удалить всех клиентов",
       "delAllClients": "Удалить всех клиентов",
       "delAllClientsConfirmTitle": "Удалить всех {count} клиентов из \"{remark}\"?",
       "delAllClientsConfirmTitle": "Удалить всех {count} клиентов из \"{remark}\"?",
       "delAllClientsConfirmContent": "Удаляет всех клиентов этого подключения и сбрасывает их записи трафика. Само подключение сохраняется. Это действие нельзя отменить.",
       "delAllClientsConfirmContent": "Удаляет всех клиентов этого подключения и сбрасывает их записи трафика. Само подключение сохраняется. Это действие нельзя отменить.",
+      "attachClients": "Привязать клиентов к…",
+      "addClientsToGroup": "Добавить клиентов в группу…",
+      "attachClientsTitle": "Привязать клиентов из «{remark}»",
+      "attachClientsDesc": "Привязывает тех же {count} клиент(ов) (с тем же UUID/паролем и общим трафиком) к выбранным входящим. Они остаются и на этом входящем.",
+      "attachClientsTargets": "Целевые входящие",
+      "attachClientsNoTargets": "Нет других совместимых входящих для привязки.",
+      "attachClientsResult": "Привязано {attached}, пропущено {skipped}.",
+      "attachClientsResultMixed": "Привязано {attached}, пропущено {skipped}, ошибок {errors}.",
+      "attachClientsSelectLabel": "Клиенты для привязки",
+      "attachClientsSearchPlaceholder": "Поиск email или комментария",
+      "attachClientsStatusDisabled": "Отключено",
+      "attachClientsSelectedCount": "{selected} из {total} выбрано",
+      "detachClients": "Отвязать клиентов",
+      "detachClientsTitle": "Отвязать клиентов из «{remark}»",
+      "detachClientsDesc": "Удаляет выбранных клиент(ов) только с этого входящего. Записи клиентов сохраняются (используйте Delete для полного удаления). У источника всего {count} клиент(ов).",
+      "detachClientsResult": "Отвязано {detached}, пропущено {skipped}.",
+      "detachClientsResultMixed": "Отвязано {detached}, пропущено {skipped}, ошибок {errors}.",
+      "detachClientsSelectLabel": "Клиенты для отвязки",
       "exportLinksTitle": "Экспортировать ссылки подключения",
       "exportLinksTitle": "Экспортировать ссылки подключения",
       "exportSubsTitle": "Экспортировать ссылки подписки",
       "exportSubsTitle": "Экспортировать ссылки подписки",
       "exportAllLinksTitle": "Экспортировать все ссылки подключений",
       "exportAllLinksTitle": "Экспортировать все ссылки подключений",
       "exportAllSubsTitle": "Экспортировать все ссылки подписок",
       "exportAllSubsTitle": "Экспортировать все ссылки подписок",
-      "inboundJsonTitle": "JSON подключения",
+      "inboundJsonTitle": "JSON входящего",
       "deleteClient": "Удалить клиента",
       "deleteClient": "Удалить клиента",
       "deleteClientContent": "Вы уверены, что хотите удалить клиента?",
       "deleteClientContent": "Вы уверены, что хотите удалить клиента?",
       "resetTrafficContent": "Вы уверены, что хотите сбросить трафик?",
       "resetTrafficContent": "Вы уверены, что хотите сбросить трафик?",
@@ -306,7 +332,7 @@
       "destinationPort": "Порт назначения",
       "destinationPort": "Порт назначения",
       "targetAddress": "Целевой адрес",
       "targetAddress": "Целевой адрес",
       "monitorDesc": "Оставьте пустым для прослушивания всех IP-адресов",
       "monitorDesc": "Оставьте пустым для прослушивания всех IP-адресов",
-      "meansNoLimit": "= Без ограничений (значение: ГБ)",
+      "meansNoLimit": "= Безлимит. (единица: ГБ)",
       "totalFlow": "Общий расход",
       "totalFlow": "Общий расход",
       "leaveBlankToNeverExpire": "Оставьте пустым, чтобы было бесконечным",
       "leaveBlankToNeverExpire": "Оставьте пустым, чтобы было бесконечным",
       "noRecommendKeepDefault": "Рекомендуется оставить настройки по умолчанию",
       "noRecommendKeepDefault": "Рекомендуется оставить настройки по умолчанию",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить лог)",
       "IPLimitlogDesc": "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить лог)",
       "IPLimitlogclear": "Очистить лог",
       "IPLimitlogclear": "Очистить лог",
       "setDefaultCert": "Установить сертификат панели",
       "setDefaultCert": "Установить сертификат панели",
-      "streamTab": "Поток",
+      "setDefaultCertEmpty": "Для панели не настроен сертификат. Сначала установите его в Настройках.",
+      "streamTab": "Stream",
       "securityTab": "Безопасность",
       "securityTab": "Безопасность",
-      "sniffingTab": "Сниффинг",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "Только метаданные",
       "sniffingMetadataOnly": "Только метаданные",
       "sniffingRouteOnly": "Только маршрутизация",
       "sniffingRouteOnly": "Только маршрутизация",
       "sniffingIpsExcluded": "Исключённые IP",
       "sniffingIpsExcluded": "Исключённые IP",
@@ -361,15 +388,14 @@
         "allHelp": "Полный объект входящего со всеми полями в одном редакторе.",
         "allHelp": "Полный объект входящего со всеми полями в одном редакторе.",
         "settings": "Настройки",
         "settings": "Настройки",
         "settingsHelp": "Обёртка блока settings Xray:",
         "settingsHelp": "Обёртка блока settings Xray:",
-        "sniffing": "Сниффинг",
+        "sniffing": "Sniffing",
         "sniffingHelp": "Обёртка блока sniffing Xray:",
         "sniffingHelp": "Обёртка блока sniffing Xray:",
-        "stream": "Поток",
+        "stream": "Stream",
         "streamHelp": "Обёртка блока stream Xray:",
         "streamHelp": "Обёртка блока stream Xray:",
         "jsonErrorPrefix": "Расширенный JSON"
         "jsonErrorPrefix": "Расширенный JSON"
       },
       },
       "telegramDesc": "Пожалуйста, укажите Chat ID Telegram. (используйте команду '/id' в боте) или ({'@'}userinfobot)",
       "telegramDesc": "Пожалуйста, укажите Chat ID Telegram. (используйте команду '/id' в боте) или ({'@'}userinfobot)",
       "subscriptionDesc": "Вы можете найти свою ссылку подписки в разделе 'Подробнее'",
       "subscriptionDesc": "Вы можете найти свою ссылку подписки в разделе 'Подробнее'",
-      "info": "Информация",
       "same": "Тот же",
       "same": "Тот же",
       "inboundData": "Данные подключений",
       "inboundData": "Данные подключений",
       "exportInbound": "Экспорт подключений",
       "exportInbound": "Экспорт подключений",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Ошибка при получении сертификата mldsa65.",
         "getNewmldsa65Error": "Ошибка при получении сертификата mldsa65.",
         "getNewVlessEncError": "Ошибка при получении сертификата VlessEnc."
         "getNewVlessEncError": "Ошибка при получении сертификата VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Вверх",
+        "moveDown": "Вниз",
+        "addAll": "Добавить все",
+        "addAllFallbackTooltip": "Добавляет строку fallback для каждого подходящего входящего, ещё не подключённого",
+        "peers": "Peers",
+        "addPeer": "Добавить peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Только для Windows. CIDR'ы автоматически добавляются в системную таблицу маршрутизации, чтобы соответствующий трафик шёл через TUN.",
+        "autoOutboundsInterface": "Авто-интерфейс исходящих",
+        "autoOutboundsInterfaceTooltip": "Физический интерфейс для исходящего трафика. Используйте 'auto' для автоопределения; включается автоматически при Auto system routes.",
+        "rewriteAddress": "Переписать адрес",
+        "rewritePort": "Переписать порт",
+        "allowedNetwork": "Разрешённая сеть",
+        "followRedirect": "Следовать redirect",
+        "accounts": "Аккаунты",
+        "allowTransparent": "Разрешить прозрачный",
+        "encryptionMethod": "Метод шифрования",
+        "visionTestseed": "Vision testseed",
+        "version": "Версия",
+        "udpIdleTimeout": "UDP idle timeout (с)",
+        "masquerade": "Masquerade",
+        "type": "Тип",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Переписать Host",
+        "skipTlsVerify": "Пропустить TLS verify",
+        "directory": "Директория",
+        "statusCode": "Код статуса",
+        "body": "Body",
+        "headers": "Заголовки",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Версия запроса",
+        "requestMethod": "Метод запроса",
+        "requestPath": "Путь запроса",
+        "requestHeaders": "Заголовки запроса",
+        "responseVersion": "Версия ответа",
+        "responseStatus": "Статус ответа",
+        "responseReason": "Причина ответа",
+        "responseHeaders": "Заголовки ответа",
+        "heartbeatPeriod": "Период heartbeat",
+        "serviceName": "Имя сервиса",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Макс. буферизованная загрузка",
+        "maxUploadSize": "Макс. размер загрузки (байт)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Server Max Header Bytes",
+        "paddingBytes": "Padding Bytes",
+        "uplinkHttpMethod": "HTTP-метод Uplink",
+        "paddingObfsMode": "Padding Obfs Mode",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding Placement",
+        "paddingMethod": "Padding Method",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Без заголовка SSE",
+        "ttiMs": "TTI (мс)",
+        "uplinkMbps": "Uplink (МБ/с)",
+        "downlinkMbps": "Downlink (МБ/с)",
+        "cwndMultiplier": "Множитель CWND",
+        "maxSendingWindow": "Макс. окно отправки",
+        "externalProxy": "External Proxy",
+        "sniPlaceholder": "SNI (по умолчанию = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "По умолчанию",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Только V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "Доверенный X-Forwarded-For",
+        "addressPortStrategy": "Стратегия адрес+порт",
+        "tryDelayMs": "Задержка попытки (мс)",
+        "prioritizeIPv6": "Приоритет IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Макс. одновременных попыток",
+        "customSockopt": "Пользовательский sockopt",
+        "addCustomOption": "Добавить опцию",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Авто",
+        "minMaxVersion": "Мин/Макс версия",
+        "rejectUnknownSni": "Отклонить неизвестный SNI",
+        "disableSystemRoot": "Отключить System Root",
+        "sessionResumption": "Возобновление сессии",
+        "oneTimeLoading": "Однократная загрузка",
+        "usageOption": "Опция использования",
+        "buildChain": "Build Chain",
+        "echKey": "ECH key",
+        "echConfig": "ECH config",
+        "getNewEchCert": "Получить новый ECH-сертификат",
+        "show": "Показать",
+        "xver": "Xver",
+        "target": "Цель",
+        "maxTimeDiff": "Макс. разница во времени (мс)",
+        "minClientVer": "Мин. версия клиента",
+        "maxClientVer": "Макс. версия клиента",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Получить новый сертификат",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Получить новый Seed"
+      },
+      "info": {
+        "mode": "Режим",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Имя интерфейса",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Интерфейс исходящих",
+        "autoSystemRoutes": "Авто-маршруты системы",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN без kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Конфиг Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Запрос",
           "request": "Запрос",
@@ -456,6 +615,20 @@
       "days": "Дни",
       "days": "Дни",
       "renew": "Автопродление",
       "renew": "Автопродление",
       "renewDesc": "Автоматическое продление после окончания. (0 = отключено) (единица: день)",
       "renewDesc": "Автоматическое продление после окончания. (0 = отключено) (единица: день)",
+      "searchPlaceholder": "Поиск email, комментария, sub ID, UUID, пароля, auth…",
+      "filterTitle": "Фильтр клиентов",
+      "clearAllFilters": "Очистить все",
+      "sortOldest": "Сначала старые",
+      "sortNewest": "Сначала новые",
+      "sortRecentlyUpdated": "Недавно обновлены",
+      "sortRecentlyOnline": "Недавно в сети",
+      "sortEmailAZ": "Email А→Я",
+      "sortEmailZA": "Email Я→А",
+      "sortMostTraffic": "Больше трафика",
+      "sortHighestRemaining": "Больше остатка",
+      "sortExpiringSoonest": "Скорее истекают",
+      "has": "Есть",
+      "hasNot": "Нет",
       "title": "Клиенты",
       "title": "Клиенты",
       "actions": "Действия",
       "actions": "Действия",
       "totalGB": "Всего отправлено/получено (ГБ)",
       "totalGB": "Всего отправлено/получено (ГБ)",
@@ -466,6 +639,9 @@
       "subId": "ID подписки",
       "subId": "ID подписки",
       "online": "В сети",
       "online": "В сети",
       "email": "Email",
       "email": "Email",
+      "group": "Группа",
+      "groupDesc": "Логическая метка для группировки связанных клиентов (например, команда, клиент, регион). Фильтруется из панели инструментов.",
+      "groupPlaceholder": "например, customer-a",
       "comment": "Комментарий",
       "comment": "Комментарий",
       "traffic": "Трафик",
       "traffic": "Трафик",
       "offline": "Не в сети",
       "offline": "Не в сети",
@@ -485,15 +661,49 @@
       "noLinks": "Нет ссылок для общего доступа — сначала привяжите клиента к входящему с поддерживаемым протоколом.",
       "noLinks": "Нет ссылок для общего доступа — сначала привяжите клиента к входящему с поддерживаемым протоколом.",
       "link": "Ссылка",
       "link": "Ссылка",
       "resetNotPossible": "Сначала привяжите этого клиента к входящему.",
       "resetNotPossible": "Сначала привяжите этого клиента к входящему.",
-      "general": "Общее",
+      "general": "Общие",
       "resetAllTraffics": "Сбросить трафик всех клиентов",
       "resetAllTraffics": "Сбросить трафик всех клиентов",
       "resetAllTrafficsTitle": "Сбросить трафик всех клиентов?",
       "resetAllTrafficsTitle": "Сбросить трафик всех клиентов?",
       "resetAllTrafficsContent": "Счётчики отправки/приёма всех клиентов сбрасываются в ноль. Квоты и срок действия не затрагиваются. Это действие нельзя отменить.",
       "resetAllTrafficsContent": "Счётчики отправки/приёма всех клиентов сбрасываются в ноль. Квоты и срок действия не затрагиваются. Это действие нельзя отменить.",
-      "empty": "Клиентов пока нет — добавьте первого, чтобы начать.",
       "deleteConfirmTitle": "Удалить клиента {email}?",
       "deleteConfirmTitle": "Удалить клиента {email}?",
       "deleteConfirmContent": "Клиент будет удалён из всех привязанных входящих, а его запись трафика будет уничтожена. Это действие нельзя отменить.",
       "deleteConfirmContent": "Клиент будет удалён из всех привязанных входящих, а его запись трафика будет уничтожена. Это действие нельзя отменить.",
       "deleteSelected": "Удалить ({count})",
       "deleteSelected": "Удалить ({count})",
       "adjustSelected": "Изменить ({count})",
       "adjustSelected": "Изменить ({count})",
+      "subLinksSelected": "Sub-ссылки ({count})",
+      "addToGroupTitle": "Добавить {count} клиент(ов) в группу",
+      "addToGroupTooltip": "Выберите существующую группу или введите новое имя. Используйте Ungroup, чтобы удалить клиентов из их текущей группы.",
+      "addToGroupPlaceholder": "Имя группы",
+      "addToGroupSuccessToast": "{count} клиент(ов) добавлено в {group}",
+      "ungroupSuccessToast": "Группа очищена у {count} клиент(ов)",
+      "ungroup": "Разгруппировать",
+      "ungroupConfirmTitle": "Удалить {count} клиент(ов) из их группы?",
+      "ungroupConfirmContent": "Очищает метку группы у каждого выбранного клиента. Сами клиенты сохраняются (используйте Delete для полного удаления).",
+      "addToGroup": "Добавить в группу",
+      "attach": "Привязать",
+      "adjust": "Корректировка",
+      "subLinks": "Sub-ссылки",
+      "selectedCount": "{count} выбрано",
+      "attachSelected": "Привязать ({count})",
+      "attachToInboundsTitle": "Привязать {count} клиент(ов) к входящим",
+      "attachToInboundsDesc": "Привязывает выбранных {count} клиент(ов) (тот же UUID/пароль и общий трафик) к выбранным входящим. Существующие привязки сохраняются.",
+      "attachToInboundsTargets": "Целевые входящие",
+      "attachToInboundsNoTargets": "Нет доступных многопользовательских входящих для привязки.",
+      "detachSelected": "Отвязать ({count})",
+      "detach": "Отвязать",
+      "detachFromInboundsTitle": "Отвязать {count} клиент(ов) от входящих",
+      "detachFromInboundsDesc": "Удаляет выбранных {count} клиент(ов) из выбранных входящих. Пары, где клиент не был привязан, тихо пропускаются. Записи клиентов сохраняются (используйте Delete для полного удаления).",
+      "detachFromInboundsTargets": "Входящие для отвязки",
+      "detachFromInboundsNoTargets": "Нет доступных многопользовательских входящих.",
+      "detachFromInboundsResult": "Отвязано {detached}, пропущено {skipped}.",
+      "detachFromInboundsResultMixed": "Отвязано {detached}, пропущено {skipped}, ошибок {errors}.",
+      "subLinksTitle": "Sub-ссылки ({count})",
+      "subLinkColumn": "URL подписки",
+      "subJsonLinkColumn": "URL JSON-подписки",
+      "subLinksCopyAll": "Копировать все",
+      "subLinksCopiedAll": "Скопировано {count} ссылок",
+      "subLinksEmpty": "Ни у одного из выбранных клиентов нет ID подписки.",
+      "subLinksDisabled": "Сервис подписки отключён.",
+      "subLinksDisabledHint": "Включите подписку в Настройки панели → Подписка для генерации ссылок.",
       "bulkDeleteConfirmTitle": "Удалить {count} клиентов?",
       "bulkDeleteConfirmTitle": "Удалить {count} клиентов?",
       "bulkDeleteConfirmContent": "Каждый выбранный клиент удаляется из всех привязанных входящих, его запись трафика уничтожается. Это действие нельзя отменить.",
       "bulkDeleteConfirmContent": "Каждый выбранный клиент удаляется из всех привязанных входящих, его запись трафика уничтожается. Это действие нельзя отменить.",
       "bulkAdjustTitle": "Изменить {count} клиентов",
       "bulkAdjustTitle": "Изменить {count} клиентов",
@@ -504,11 +714,12 @@
       "delDepleted": "Удалить исчерпанных",
       "delDepleted": "Удалить исчерпанных",
       "delDepletedConfirmTitle": "Удалить исчерпанных клиентов?",
       "delDepletedConfirmTitle": "Удалить исчерпанных клиентов?",
       "delDepletedConfirmContent": "Удаляются все клиенты, у которых исчерпана квота трафика или истёк срок. Это действие нельзя отменить.",
       "delDepletedConfirmContent": "Удаляются все клиенты, у которых исчерпана квота трафика или истёк срок. Это действие нельзя отменить.",
-      "auth": "Auth",
-      "hysteriaAuth": "Auth для Hysteria",
+      "auth": "Авторизация",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "VMess Security",
+      "reverseTag": "Обратный тег",
       "reverseTagPlaceholder": "Необязательный Reverse tag",
       "reverseTagPlaceholder": "Необязательный Reverse tag",
       "telegramId": "ID пользователя Telegram",
       "telegramId": "ID пользователя Telegram",
       "telegramIdPlaceholder": "Числовой ID пользователя Telegram (0 = нет)",
       "telegramIdPlaceholder": "Числовой ID пользователя Telegram (0 = нет)",
@@ -528,13 +739,51 @@
         "delDepleted": "Удалено исчерпанных клиентов: {count}"
         "delDepleted": "Удалено исчерпанных клиентов: {count}"
       }
       }
     },
     },
+    "groups": {
+      "title": "Группы",
+      "name": "Имя",
+      "clientCount": "Клиентов в группе",
+      "totalGroups": "Всего групп",
+      "totalGroupedClients": "Клиенты с группой",
+      "emptyGroups": "Пустые группы",
+      "addGroup": "Добавить группу",
+      "createSuccess": "Группа «{name}» создана.",
+      "rename": "Переименовать",
+      "renameTitle": "Переименовать {name}",
+      "renameCollision": "Группа с именем «{name}» уже существует.",
+      "renameSuccess": "Группа переименована для {count} клиент(ов).",
+      "deleteConfirmTitle": "Удалить группу {name}?",
+      "deleteConfirmContent": "Это удаляет группу и очищает её метку у {count} клиент(ов). Сами клиенты не удаляются.",
+      "deleteSuccess": "Группа очищена у {count} клиент(ов).",
+      "resetTraffic": "Сбросить трафик",
+      "resetConfirmTitle": "Сбросить трафик группы {name}?",
+      "resetConfirmContent": "Это обнулит up/down для всех {count} клиент(ов) в этой группе.",
+      "resetSuccess": "Сброшен трафик у {count} клиент(ов).",
+      "adjustSuccess": "Скорректировано {count} клиент(ов) в {name}.",
+      "emptyForAction": "В этой группе пока нет клиентов.",
+      "deleteGroupOnly": "Удалить группу (сохранить клиентов)",
+      "deleteClients": "Удалить клиентов группы",
+      "deleteClientsConfirmTitle": "Удалить всех клиентов в {name}?",
+      "deleteClientsConfirmContent": "Это безвозвратно удаляет {count} клиент(ов) вместе с их записями трафика. Метка группы также очищается. Это нельзя отменить.",
+      "deleteClientsSuccess": "Удалено {count} клиент(ов).",
+      "deleteClientsMixed": "{ok} удалено, {failed} пропущено",
+      "addToGroup": "Добавить клиентов…",
+      "addToGroupTitle": "Добавить клиентов в группу «{name}»",
+      "addToGroupDesc": "Выберите клиентов для добавления в эту группу. Существующие привязки к входящим сохраняются; меняется только метка группы. Клиенты, уже входящие в эту группу, не показываются.",
+      "addToGroupEmpty": "Нет других клиентов для добавления.",
+      "addToGroupResult": "Добавлено {count} клиент(ов) в {name}.",
+      "removeFromGroup": "Удалить клиентов…",
+      "removeFromGroupTitle": "Удалить клиентов из группы «{name}»",
+      "removeFromGroupDesc": "Выберите участников для удаления из этой группы. Сами клиенты сохраняются (используйте «Удалить клиентов группы» для полного удаления).",
+      "removeFromGroupResult": "Удалено {count} клиент(ов) из {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Узлы",
       "title": "Узлы",
       "addNode": "Добавить узел",
       "addNode": "Добавить узел",
-      "editNode": "Редактировать узел",
+      "editNode": "Изменить узел",
       "totalNodes": "Всего узлов",
       "totalNodes": "Всего узлов",
-      "onlineNodes": "Онлайн",
-      "offlineNodes": "Офлайн",
+      "onlineNodes": "В сети",
+      "offlineNodes": "Не в сети",
       "avgLatency": "Средняя задержка",
       "avgLatency": "Средняя задержка",
       "name": "Имя",
       "name": "Имя",
       "namePlaceholder": "напр. de-frankfurt-1",
       "namePlaceholder": "напр. de-frankfurt-1",
@@ -544,7 +793,7 @@
       "address": "Адрес",
       "address": "Адрес",
       "port": "Порт",
       "port": "Порт",
       "basePath": "Базовый путь",
       "basePath": "Базовый путь",
-      "apiToken": "Токен API",
+      "apiToken": "API Токен",
       "apiTokenPlaceholder": "Токен со страницы Настроек удалённой панели",
       "apiTokenPlaceholder": "Токен со страницы Настроек удалённой панели",
       "apiTokenHint": "Удалённая панель показывает свой токен API в разделе Настройки → Токен API.",
       "apiTokenHint": "Удалённая панель показывает свой токен API в разделе Настройки → Токен API.",
       "regenerate": "Сгенерировать токен заново",
       "regenerate": "Сгенерировать токен заново",
@@ -555,7 +804,7 @@
       "status": "Статус",
       "status": "Статус",
       "cpu": "CPU",
       "cpu": "CPU",
       "mem": "Память",
       "mem": "Память",
-      "uptime": "Время работы",
+      "uptime": "Аптайм",
       "latency": "Задержка",
       "latency": "Задержка",
       "lastHeartbeat": "Последний пинг",
       "lastHeartbeat": "Последний пинг",
       "xrayVersion": "Версия Xray",
       "xrayVersion": "Версия Xray",
@@ -570,8 +819,8 @@
       "deleteConfirmTitle": "Удалить узел \"{name}\"?",
       "deleteConfirmTitle": "Удалить узел \"{name}\"?",
       "deleteConfirmContent": "Это остановит мониторинг узла. Сама удалённая панель не будет затронута.",
       "deleteConfirmContent": "Это остановит мониторинг узла. Сама удалённая панель не будет затронута.",
       "statusValues": {
       "statusValues": {
-        "online": "Онлайн",
-        "offline": "Офлайн",
+        "online": "В сети",
+        "offline": "Не в сети",
         "unknown": "Неизвестно"
         "unknown": "Неизвестно"
       },
       },
       "toasts": {
       "toasts": {
@@ -590,7 +839,7 @@
       "title": "Настройки",
       "title": "Настройки",
       "save": "Сохранить",
       "save": "Сохранить",
       "infoDesc": "Сохраните изменения и перезапустите панель для их применения.",
       "infoDesc": "Сохраните изменения и перезапустите панель для их применения.",
-      "restartPanel": "Перезапуск панели",
+      "restartPanel": "Перезапустить панель",
       "restartPanelDesc": "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера",
       "restartPanelDesc": "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера",
       "restartPanelSuccess": "Панель успешно перезапущена",
       "restartPanelSuccess": "Панель успешно перезапущена",
       "actions": "Действия",
       "actions": "Действия",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "Базовый путь по умолчанию \"/\" широко известен — измените его на случайный.",
       "warnDefaultBasePath": "Базовый путь по умолчанию \"/\" широко известен — измените его на случайный.",
       "warnDefaultSubPath": "Путь подписки по умолчанию \"/sub/\" широко известен — измените его.",
       "warnDefaultSubPath": "Путь подписки по умолчанию \"/sub/\" широко известен — измените его.",
       "warnDefaultJsonPath": "JSON-путь подписки по умолчанию \"/json/\" широко известен — измените его.",
       "warnDefaultJsonPath": "JSON-путь подписки по умолчанию \"/json/\" широко известен — измените его.",
-      "TGBotSettings": "Telegram-Бот",
+      "TGBotSettings": "Telegram-бот",
       "panelListeningIP": "IP-адрес для управления панелью",
       "panelListeningIP": "IP-адрес для управления панелью",
       "panelListeningIPDesc": "Оставьте пустым для подключения с любого IP",
       "panelListeningIPDesc": "Оставьте пустым для подключения с любого IP",
       "panelListeningDomain": "Домен панели",
       "panelListeningDomain": "Домен панели",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Введите полный путь, начинающийся с '/'",
       "publicKeyPathDesc": "Введите полный путь, начинающийся с '/'",
       "privateKeyPath": "Путь к файлу приватного ключа сертификата панели",
       "privateKeyPath": "Путь к файлу приватного ключа сертификата панели",
       "privateKeyPathDesc": "Введите полный путь, начинающийся с '/'",
       "privateKeyPathDesc": "Введите полный путь, начинающийся с '/'",
-      "panelUrlPath": "Корневой путь URL адреса панели",
+      "panelUrlPath": "URI-путь",
       "panelUrlPathDesc": "Должен начинаться с '/' и заканчиваться '/'",
       "panelUrlPathDesc": "Должен начинаться с '/' и заканчиваться '/'",
       "pageSize": "Размер нумерации страниц",
       "pageSize": "Размер нумерации страниц",
       "pageSizeDesc": "Определить размер страницы для таблицы подключений. Установите 0, чтобы отключить",
       "pageSizeDesc": "Определить размер страницы для таблицы подключений. Установите 0, чтобы отключить",
+      "panelProxy": "Сетевой прокси панели",
+      "panelProxyDesc": "Маршрутизирует исходящие запросы самой панели (обновления geo, проверки версий Xray/панели, Telegram) через этот прокси для обхода серверной фильтрации GitHub/Telegram. Принимает socks5:// или http(s)://, напр. локальный SOCKS-входящий Xray. Оставьте пустым для прямого подключения.",
       "remarkModel": "Модель примечания и символ разделения",
       "remarkModel": "Модель примечания и символ разделения",
       "datepicker": "Тип календаря",
       "datepicker": "Тип календаря",
       "datepickerPlaceholder": "Выберите дату",
       "datepickerPlaceholder": "Выберите дату",
@@ -630,11 +881,11 @@
       "newPassword": "Новый пароль",
       "newPassword": "Новый пароль",
       "telegramBotEnable": "Включить Telegram бота",
       "telegramBotEnable": "Включить Telegram бота",
       "telegramBotEnableDesc": "Доступ к функциям панели через Telegram-бота",
       "telegramBotEnableDesc": "Доступ к функциям панели через Telegram-бота",
-      "telegramToken": "Токен Telegram бота",
+      "telegramToken": "Telegram-токен",
       "telegramTokenDesc": "Необходимо получить токен у менеджера ботов Telegram {'@'}botfather",
       "telegramTokenDesc": "Необходимо получить токен у менеджера ботов Telegram {'@'}botfather",
-      "telegramProxy": "Прокси-сервер Socks5",
+      "telegramProxy": "SOCKS-прокси",
       "telegramProxyDesc": "Если для подключения к Telegram вам нужен прокси Socks5, настройте его параметры согласно руководству.",
       "telegramProxyDesc": "Если для подключения к Telegram вам нужен прокси Socks5, настройте его параметры согласно руководству.",
-      "telegramAPIServer": "API-сервер Telegram",
+      "telegramAPIServer": "Telegram API Server",
       "telegramAPIServerDesc": "Используемый API-сервер Telegram. Оставьте пустым, чтобы использовать сервер по умолчанию.",
       "telegramAPIServerDesc": "Используемый API-сервер Telegram. Оставьте пустым, чтобы использовать сервер по умолчанию.",
       "telegramChatId": "User ID администратора бота",
       "telegramChatId": "User ID администратора бота",
       "telegramChatIdDesc": "Один или несколько User ID администратора(-ов) Telegram-бота. Для получения User ID используйте {'@'}userinfobot или команду '/id' в боте.",
       "telegramChatIdDesc": "Один или несколько User ID администратора(-ов) Telegram-бота. Для получения User ID используйте {'@'}userinfobot или команду '/id' в боте.",
@@ -658,6 +909,8 @@
       "subEnable": "Включить подписку",
       "subEnable": "Включить подписку",
       "subEnableDesc": "Функция подписки с отдельной конфигурацией",
       "subEnableDesc": "Функция подписки с отдельной конфигурацией",
       "subJsonEnable": "Включить/отключить JSON-эндпоинт подписки независимо.",
       "subJsonEnable": "Включить/отключить JSON-эндпоинт подписки независимо.",
+      "subJsonEnableTitle": "JSON-подписка",
+      "subClashEnableTitle": "Подписка Clash / Mihomo",
       "subTitle": "Заголовок подписки",
       "subTitle": "Заголовок подписки",
       "subTitleDesc": "Название подписки, которое видит клиент в VPN-клиенте",
       "subTitleDesc": "Название подписки, которое видит клиент в VPN-клиенте",
       "subSupportUrl": "URL поддержки",
       "subSupportUrl": "URL поддержки",
@@ -678,13 +931,13 @@
       "subCertPathDesc": "Введите полный путь, начинающийся с '/'",
       "subCertPathDesc": "Введите полный путь, начинающийся с '/'",
       "subKeyPath": "Путь к файлу приватного ключа сертификата подписки",
       "subKeyPath": "Путь к файлу приватного ключа сертификата подписки",
       "subKeyPathDesc": "Введите полный путь, начинающийся с '/'",
       "subKeyPathDesc": "Введите полный путь, начинающийся с '/'",
-      "subPath": "Корневой путь URL-адреса подписки",
+      "subPath": "URI-путь",
       "subPathDesc": "Должен начинаться с '/' и заканчиваться на '/'",
       "subPathDesc": "Должен начинаться с '/' и заканчиваться на '/'",
       "subDomain": "Домен прослушивания",
       "subDomain": "Домен прослушивания",
       "subDomainDesc": "Оставьте пустым по умолчанию, чтобы слушать все домены и IP-адреса",
       "subDomainDesc": "Оставьте пустым по умолчанию, чтобы слушать все домены и IP-адреса",
       "subUpdates": "Интервалы обновления подписки",
       "subUpdates": "Интервалы обновления подписки",
       "subUpdatesDesc": "Интервал между обновлениями в клиентском приложении (в часах)",
       "subUpdatesDesc": "Интервал между обновлениями в клиентском приложении (в часах)",
-      "subEncrypt": "Шифровать конфиги",
+      "subEncrypt": "Кодировать",
       "subEncryptDesc": "Шифровать возвращенные конфиги в подписке",
       "subEncryptDesc": "Шифровать возвращенные конфиги в подписке",
       "subShowInfo": "Показать информацию об использовании",
       "subShowInfo": "Показать информацию об использовании",
       "subShowInfoDesc": "Отображать остаток трафика и дату окончания после имени конфигурации",
       "subShowInfoDesc": "Отображать остаток трафика и дату окончания после имени конфигурации",
@@ -693,7 +946,7 @@
       "subURI": "URI обратного прокси",
       "subURI": "URI обратного прокси",
       "subURIDesc": "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами",
       "subURIDesc": "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами",
       "externalTrafficInformEnable": "Информация о внешнем трафике",
       "externalTrafficInformEnable": "Информация о внешнем трафике",
-      "externalTrafficInformEnableDesc": "Информировать внешний API о каждом обновлении трафика",
+      "externalTrafficInformEnableDesc": "Уведомлять внешний API при каждом обновлении трафика.",
       "externalTrafficInformURI": "URI информации о внешнем трафике",
       "externalTrafficInformURI": "URI информации о внешнем трафике",
       "externalTrafficInformURIDesc": "Обновления трафика отправляются на этот URI",
       "externalTrafficInformURIDesc": "Обновления трафика отправляются на этот URI",
       "restartXrayOnClientDisable": "Перезапускать Xray после автоотключения",
       "restartXrayOnClientDisable": "Перезапускать Xray после автоотключения",
@@ -703,6 +956,54 @@
       "fragmentSett": "Настройки фрагментации",
       "fragmentSett": "Настройки фрагментации",
       "noisesDesc": "Включить Noises.",
       "noisesDesc": "Включить Noises.",
       "noisesSett": "Настройки Noises",
       "noisesSett": "Настройки Noises",
+      "trustedProxyCidrs": "Доверенные CIDR прокси",
+      "trustedProxyCidrsDesc": "IP/CIDR через запятую, которым разрешено устанавливать заголовки forwarded host, proto и client IP.",
+      "ldap": {
+        "enable": "Включить LDAP-синхронизацию",
+        "host": "LDAP-хост",
+        "port": "Порт LDAP",
+        "useTls": "Использовать TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Настроено; оставьте пустым, чтобы сохранить текущий пароль.",
+        "passwordUnconfigured": "Не настроено.",
+        "passwordPlaceholder": "Настроено — введите новое значение для замены",
+        "baseDn": "Base DN",
+        "userFilter": "Фильтр пользователя",
+        "userAttr": "Атрибут пользователя (username/email)",
+        "vlessField": "Атрибут VLESS-флага",
+        "flagField": "Общий атрибут флага (опц.)",
+        "flagFieldDesc": "Если задано, переопределяет флаг VLESS — напр. shadowInactive.",
+        "truthyValues": "Truthy-значения",
+        "truthyValuesDesc": "Через запятую; по умолчанию: true,1,yes,on",
+        "invertFlag": "Инвертировать флаг",
+        "invertFlagDesc": "Включите, когда атрибут означает «отключено» (напр. shadowInactive).",
+        "syncSchedule": "Расписание синхронизации",
+        "syncScheduleDesc": "Строка типа cron, напр. @every 1m",
+        "inboundTags": "Теги входящих",
+        "inboundTagsDesc": "Входящие, на которых LDAP-синхронизация может авто-создавать или авто-удалять клиентов.",
+        "noInbounds": "Входящие не найдены. Сначала создайте входящий.",
+        "autoCreate": "Авто-создание клиентов",
+        "autoDelete": "Авто-удаление клиентов",
+        "defaultTotalGb": "Объём по умолчанию (ГБ)",
+        "defaultExpiryDays": "Срок по умолчанию (дни)",
+        "defaultIpLimit": "Лимит IP по умолчанию"
+      },
+      "subFormats": {
+        "packets": "Пакеты",
+        "length": "Длина",
+        "interval": "Интервал",
+        "maxSplit": "Макс. разбиение",
+        "noises": "Шумы",
+        "noiseItem": "Шум №{n}",
+        "type": "Тип",
+        "packet": "Пакет",
+        "delayMs": "Задержка (мс)",
+        "applyTo": "Применить к",
+        "addNoise": "+ Шум",
+        "concurrency": "Параллелизм",
+        "xudpConcurrency": "Параллелизм xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Передача нескольких независимых потоков данных в одном соединении.",
       "muxDesc": "Передача нескольких независимых потоков данных в одном соединении.",
       "muxSett": "Настройки Mux",
       "muxSett": "Настройки Mux",
@@ -758,6 +1059,9 @@
       "save": "Сохранить",
       "save": "Сохранить",
       "restart": "Перезапуск Xray",
       "restart": "Перезапуск Xray",
       "restartSuccess": "Xray успешно перезапущен",
       "restartSuccess": "Xray успешно перезапущен",
+      "restartOutputTitle": "Вывод перезапуска Xray",
+      "restartConfirmTitle": "Перезапустить xray?",
+      "restartConfirmContent": "Перезагружает сервис xray с сохранённой конфигурацией.",
       "stopSuccess": "Xray успешно остановлен",
       "stopSuccess": "Xray успешно остановлен",
       "restartError": "Произошла ошибка при перезапуске Xray.",
       "restartError": "Произошла ошибка при перезапуске Xray.",
       "stopError": "Произошла ошибка при остановке Xray.",
       "stopError": "Произошла ошибка при остановке Xray.",
@@ -765,7 +1069,7 @@
       "advancedTemplate": "Расширенный шаблон",
       "advancedTemplate": "Расширенный шаблон",
       "generalConfigs": "Основные настройки",
       "generalConfigs": "Основные настройки",
       "generalConfigsDesc": "Эти параметры описывают общие настройки",
       "generalConfigsDesc": "Эти параметры описывают общие настройки",
-      "logConfigs": "Логи",
+      "logConfigs": "Лог",
       "logConfigsDesc": "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!",
       "logConfigsDesc": "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!",
       "blockConfigsDesc": "Настройте, чтобы клиенты не имели доступа к определенным протоколам",
       "blockConfigsDesc": "Настройте, чтобы клиенты не имели доступа к определенным протоколам",
       "basicRouting": "Базовые соединения",
       "basicRouting": "Базовые соединения",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "URL для теста исходящего",
       "outboundTestUrl": "URL для теста исходящего",
       "outboundTestUrlDesc": "URL для проверки подключения исходящего",
       "outboundTestUrlDesc": "URL для проверки подключения исходящего",
       "Torrent": "Заблокировать BitTorrent",
       "Torrent": "Заблокировать BitTorrent",
-      "Inbounds": "Входящие подключения",
+      "Inbounds": "Входящие",
       "InboundsDesc": "Изменение шаблона конфигурации для подключения определенных клиентов",
       "InboundsDesc": "Изменение шаблона конфигурации для подключения определенных клиентов",
-      "Outbounds": "Исходящие подключения",
+      "Outbounds": "Исходящие",
       "Balancers": "Балансировщик",
       "Balancers": "Балансировщик",
+      "balancerTagRequired": "Тег обязателен",
+      "balancerSelectorRequired": "Выберите хотя бы одно исходящее",
       "OutboundsDesc": "Изменение шаблона конфигурации, чтобы определить исходящие подключения для этого сервера",
       "OutboundsDesc": "Изменение шаблона конфигурации, чтобы определить исходящие подключения для этого сервера",
       "Routings": "Маршрутизация",
       "Routings": "Маршрутизация",
       "RoutingsDesc": "Важен приоритет каждого правила!",
       "RoutingsDesc": "Важен приоритет каждого правила!",
@@ -827,11 +1133,78 @@
         "inbound": "Входящее подключение",
         "inbound": "Входящее подключение",
         "outbound": "Исходящее подключение",
         "outbound": "Исходящее подключение",
         "balancer": "Балансировщик",
         "balancer": "Балансировщик",
-        "info": "Информация",
+        "info": "Инфо",
         "add": "Создать правило",
         "add": "Создать правило",
         "edit": "Редактировать правило",
         "edit": "Редактировать правило",
         "useComma": "Элементы, разделённые запятыми"
         "useComma": "Элементы, разделённые запятыми"
       },
       },
+      "routing": {
+        "dragToReorder": "Перетащите для изменения порядка"
+      },
+      "ruleForm": {
+        "sourceIps": "IP источника",
+        "sourcePort": "Порт источника",
+        "vlessRoute": "VLESS route",
+        "attributes": "Атрибуты",
+        "value": "Значение",
+        "user": "Пользователь",
+        "inboundTags": "Теги входящих",
+        "outboundTag": "Тег исходящего",
+        "balancerTag": "Тег балансировщика",
+        "balancerTagTooltip": "Направляет трафик через один из настроенных балансировщиков нагрузки"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Тег уже используется другим исходящим",
+        "tagRequired": "Тег обязателен",
+        "tagPlaceholder": "уникальный-тег",
+        "localIpPlaceholder": "локальный IP",
+        "addressRequired": "Адрес обязателен",
+        "portRequired": "Порт обязателен",
+        "optional": "опционально",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "Версия UoT",
+        "inboundTag": "Тег входящего",
+        "inboundTagPlaceholder": "тег входящего в правилах маршрутизации",
+        "responseType": "Тип ответа",
+        "rewriteNetwork": "Переписать сеть",
+        "unchanged": "(без изменений)",
+        "unchangedAddress": "(без изменений) напр. 1.1.1.1",
+        "rules": "Правила",
+        "ruleN": "Правило {n}",
+        "action": "Действие",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Финальные правила",
+        "overrideXrayPrivateIp": "Переопределить дефолтный блок частных IP в Xray",
+        "blockDelay": "Задержка блока (мс)",
+        "reverseSniffing": "Обратный sniffing",
+        "workers": "Воркеры",
+        "reserved": "Зарезервировано",
+        "minUploadInterval": "Мин. интервал загрузки (мс)",
+        "maxUploadSizeBytes": "Макс. размер загрузки (байт)",
+        "uplinkChunkSize": "Размер chunk Uplink",
+        "noGrpcHeader": "Без gRPC-заголовка",
+        "maxConcurrency": "Макс. параллелизм",
+        "maxConnections": "Макс. соединений",
+        "maxReuseTimes": "Макс. повторных использований",
+        "maxRequestTimes": "Макс. запросов",
+        "maxReusableSecs": "Макс. секунд повторного использования",
+        "keepAlivePeriod": "Период keep alive",
+        "authPassword": "Пароль авторизации",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "имя сервера",
+        "verifyPeerName": "Проверять имя peer",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Интервал keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Интерфейс",
+        "ipv6Only": "Только IPv6",
+        "acceptProxyProtocol": "Принимать proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (мс)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (с)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Создать исходящее подключение",
         "addOutbound": "Создать исходящее подключение",
         "addReverse": "Создать реверс-прокси",
         "addReverse": "Создать реверс-прокси",
@@ -846,8 +1219,8 @@
         "reverse": "Реверс-прокси",
         "reverse": "Реверс-прокси",
         "domain": "Домен",
         "domain": "Домен",
         "type": "Тип",
         "type": "Тип",
-        "bridge": "Мост",
-        "portal": "Портал",
+        "bridge": "Bridge",
+        "portal": "Portal",
         "link": "Ссылка",
         "link": "Ссылка",
         "intercon": "Соединение",
         "intercon": "Соединение",
         "settings": "Настройки",
         "settings": "Настройки",
@@ -860,6 +1233,8 @@
         "testSuccess": "Тест успешен",
         "testSuccess": "Тест успешен",
         "testFailed": "Тест не пройден",
         "testFailed": "Тест не пройден",
         "testError": "Не удалось протестировать исходящее подключение",
         "testError": "Не удалось протестировать исходящее подключение",
+        "testModeTooltip": "TCP: быстрый dial-only probe. HTTP: полный запрос через xray.",
+        "testAll": "Тестировать все",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Токен доступа",
         "accessToken": "Токен доступа",
         "country": "Страна",
         "country": "Страна",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "Селекторы",
         "balancerSelectors": "Селекторы",
         "tag": "Тег",
         "tag": "Тег",
         "tagDesc": "Уникальный тег",
         "tagDesc": "Уникальный тег",
+        "tagDuplicate": "Тег уже используется другим балансировщиком",
+        "tagPlaceholder": "уникальный тег балансировщика",
+        "selector": "Селектор",
+        "fallback": "Fallback",
+        "expected": "Ожидаемое",
+        "expectedPlaceholder": "оптимальное число узлов",
+        "maxRtt": "Макс. RTT",
+        "tolerance": "Допуск",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
         "balancerDesc": "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Уровень пользователя",
         "userLevel": "Уровень пользователя",
         "userLevelDesc": "Все соединения, установленные через этот входящий поток, будут использовать этот уровень пользователя. Значение по умолчанию - 0"
         "userLevelDesc": "Все соединения, установленные через этот входящий поток, будут использовать этот уровень пользователя. Значение по умолчанию - 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Приватный ключ",
+        "noServers": "Серверов для выбранной страны не найдено",
+        "noPublicKey": "Выбранный сервер не сообщает публичный ключ NordLynx.",
+        "outboundAdded": "Исходящий NordVPN добавлен",
+        "outboundUpdated": "Исходящий NordVPN обновлён"
+      },
+      "warp": {
+        "licenseError": "Не удалось установить лицензию WARP.",
+        "fetchFirst": "Сначала получите WARP-конфиг.",
+        "createAccount": "Создать аккаунт WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID устройства",
+        "licenseKey": "Лицензионный ключ",
+        "privateKey": "Приватный ключ",
+        "deleteAccount": "Удалить аккаунт",
+        "settings": "Настройки",
+        "licenseKeyLabel": "Лицензионный ключ WARP / WARP+",
+        "key": "Ключ",
+        "keyPlaceholder": "26-символьный ключ WARP+",
+        "accountInfo": "Информация об аккаунте",
+        "deviceName": "Имя устройства",
+        "deviceModel": "Модель устройства",
+        "deviceEnabled": "Устройство включено",
+        "accountType": "Тип аккаунта",
+        "role": "Роль",
+        "warpPlusData": "WARP+ data",
+        "quota": "Квота",
+        "usage": "Использование",
+        "addOutbound": "Добавить исходящий"
+      },
       "dns": {
       "dns": {
         "enable": "Включить DNS",
         "enable": "Включить DNS",
         "enableDesc": "Включить встроенный DNS-сервер",
         "enableDesc": "Включить встроенный DNS-сервер",
@@ -959,10 +1376,10 @@
     "hours": "Часов",
     "hours": "Часов",
     "minutes": "Минуты",
     "minutes": "Минуты",
     "unknown": "Неизвестно",
     "unknown": "Неизвестно",
-    "inbounds": "Входящие подключения",
+    "inbounds": "Входящие",
     "clients": "Клиенты",
     "clients": "Клиенты",
-    "offline": "🔴 Офлайн",
-    "online": "🟢 Онлайн",
+    "offline": "🔴 Не в сети",
+    "online": "🟢 В сети",
     "commands": {
     "commands": {
       "unknown": "❗ Неизвестная команда",
       "unknown": "❗ Неизвестная команда",
       "pleaseChoose": "👇 Пожалуйста, выберите:\r\n",
       "pleaseChoose": "👇 Пожалуйста, выберите:\r\n",
@@ -992,24 +1409,24 @@
       "2faFailed": "Ошибка 2FA",
       "2faFailed": "Ошибка 2FA",
       "report": "🕰 Запланированные отчеты: {{ .RunTime }}\r\n",
       "report": "🕰 Запланированные отчеты: {{ .RunTime }}\r\n",
       "datetime": "⏰ Дата и время: {{ .DateTime }}\r\n",
       "datetime": "⏰ Дата и время: {{ .DateTime }}\r\n",
-      "hostname": "💻 Имя хоста: {{ .Hostname }}\r\n",
+      "hostname": "💻 Хост: {{ .Hostname }}\r\n",
       "version": "🚀 Версия X-UI: {{ .Version }}\r\n",
       "version": "🚀 Версия X-UI: {{ .Version }}\r\n",
       "xrayVersion": "📡 Версия Xray: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Версия Xray: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
-      "ips": "🔢 IP-адреса:\r\n{{ .IPs }}\r\n",
+      "ips": "🔢 IP:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ Время работы сервера: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ Время работы сервера: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 Нагрузка сервера: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 Нагрузка сервера: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 ОЗУ сервера: {{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 Количество TCP-соединений: {{ .Count }}\r\n",
-      "udpCount": "🔸 Количество UDP-соединений: {{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 Трафик: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 Трафик: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Состояние Xray: {{ .State }}\r\n",
+      "xrayStatus": "ℹ️ Статус: {{ .State }}\r\n",
       "username": "👤 Имя пользователя: {{ .Username }}\r\n",
       "username": "👤 Имя пользователя: {{ .Username }}\r\n",
       "reason": "❗️ Причина: {{ .Reason }}\r\n",
       "reason": "❗️ Причина: {{ .Reason }}\r\n",
       "time": "⏰ Время: {{ .Time }}\r\n",
       "time": "⏰ Время: {{ .Time }}\r\n",
-      "inbound": "📍 Входящее подключение: {{ .Remark }}\r\n",
+      "inbound": "📍 Входящий: {{ .Remark }}\r\n",
       "port": "🔌 Порт: {{ .Port }}\r\n",
       "port": "🔌 Порт: {{ .Port }}\r\n",
       "expire": "📅 Дата окончания: {{ .Time }}\r\n",
       "expire": "📅 Дата окончания: {{ .Time }}\r\n",
       "expireIn": "📅 Окончание через: {{ .Time }}\r\n",
       "expireIn": "📅 Окончание через: {{ .Time }}\r\n",
@@ -1018,9 +1435,9 @@
       "online": "🌐 Статус соединения: {{ .Status }}\r\n",
       "online": "🌐 Статус соединения: {{ .Status }}\r\n",
       "lastOnline": "🔙 Был(а) в сети: {{ .Time }}\r\n",
       "lastOnline": "🔙 Был(а) в сети: {{ .Time }}\r\n",
       "email": "📧 Email: {{ .Email }}\r\n",
       "email": "📧 Email: {{ .Email }}\r\n",
-      "upload": "🔼 Исходящий трафик: ↑{{ .Upload }}\r\n",
-      "download": "🔽 Входящий трафик: ↓{{ .Download }}\r\n",
-      "total": "📊 Всего: ↑↓{{ .UpDown }} из {{ .Total }}\r\n",
+      "upload": "🔼 Загрузка: ↑{{ .Upload }}\r\n",
+      "download": "🔽 Загрузка: ↓{{ .Download }}\r\n",
+      "total": "📊 Всего: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 Telegram User ID: {{ .TelegramID }}\r\n",
       "TGUser": "👤 Telegram User ID: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 Исчерпаны {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 Исчерпаны {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 Количество исчерпанных {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 Количество исчерпанных {{ .Type }}:\r\n",
@@ -1077,7 +1494,7 @@
       "ipLimit": "🔢 Лимит IP",
       "ipLimit": "🔢 Лимит IP",
       "setTGUser": "👤 Установить пользователя Telegram",
       "setTGUser": "👤 Установить пользователя Telegram",
       "toggle": "🔘 Вкл./Выкл.",
       "toggle": "🔘 Вкл./Выкл.",
-      "custom": "🔢 Свой",
+      "custom": "🔢 Своё",
       "confirmNumber": "✅ Подтвердить: {{ .Num }}",
       "confirmNumber": "✅ Подтвердить: {{ .Num }}",
       "confirmNumberAdd": "✅ Подтвердить добавление: {{ .Num }}",
       "confirmNumberAdd": "✅ Подтвердить добавление: {{ .Num }}",
       "limitTraffic": "🚧 Лимит трафика",
       "limitTraffic": "🚧 Лимит трафика",
@@ -1091,7 +1508,7 @@
       "change_password": "⚙️🔑 Пароль",
       "change_password": "⚙️🔑 Пароль",
       "change_email": "⚙️📧 Email",
       "change_email": "⚙️📧 Email",
       "change_comment": "⚙️💬 Комментарий",
       "change_comment": "⚙️💬 Комментарий",
-      "change_flow": "⚙️🚦 Поток",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "Сбросить весь трафик",
       "ResetAllTraffics": "Сбросить весь трафик",
       "SortedTrafficUsageReport": "Отсортированный отчет об использовании трафика"
       "SortedTrafficUsageReport": "Отсортированный отчет об использовании трафика"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Выберите входящее подключение"
       "chooseInbound": "Выберите входящее подключение"
     }
     }
   }
   }
-}
+}

+ 454 - 37
web/translation/tr-TR.json

@@ -8,15 +8,22 @@
   "save": "Kaydet",
   "save": "Kaydet",
   "logout": "Çıkış Yap",
   "logout": "Çıkış Yap",
   "create": "Oluştur",
   "create": "Oluştur",
+  "add": "Ekle",
+  "remove": "Kaldır",
   "update": "Güncelle",
   "update": "Güncelle",
   "copy": "Kopyala",
   "copy": "Kopyala",
   "copied": "Kopyalandı",
   "copied": "Kopyalandı",
+  "more": "daha",
   "download": "İndir",
   "download": "İndir",
   "remark": "Açıklama",
   "remark": "Açıklama",
   "enable": "Etkin",
   "enable": "Etkin",
   "protocol": "Protokol",
   "protocol": "Protokol",
   "search": "Ara",
   "search": "Ara",
-  "filter": "Filtrele",
+  "filter": "Filtre",
+  "all": "Tümü",
+  "from": "Başlangıç",
+  "to": "Bitiş",
+  "done": "Tamam",
   "loading": "Yükleniyor...",
   "loading": "Yükleniyor...",
   "refresh": "Yenile",
   "refresh": "Yenile",
   "clear": "Temizle",
   "clear": "Temizle",
@@ -27,7 +34,7 @@
   "check": "Kontrol Et",
   "check": "Kontrol Et",
   "indefinite": "Belirsiz",
   "indefinite": "Belirsiz",
   "unlimited": "Sınırsız",
   "unlimited": "Sınırsız",
-  "none": "Hiçbiri",
+  "none": "Yok",
   "qrCode": "QR Kod",
   "qrCode": "QR Kod",
   "info": "Daha Fazla Bilgi",
   "info": "Daha Fazla Bilgi",
   "edit": "Düzenle",
   "edit": "Düzenle",
@@ -39,9 +46,9 @@
   "encryption": "Şifreleme",
   "encryption": "Şifreleme",
   "useIPv4ForHost": "Ana bilgisayar için IPv4 kullan",
   "useIPv4ForHost": "Ana bilgisayar için IPv4 kullan",
   "transmission": "İletim",
   "transmission": "İletim",
-  "host": "Sunucu",
+  "host": "Host",
   "path": "Yol",
   "path": "Yol",
-  "camouflage": "Kandırma",
+  "camouflage": "Karartma",
   "status": "Durum",
   "status": "Durum",
   "enabled": "Etkin",
   "enabled": "Etkin",
   "disabled": "Devre Dışı",
   "disabled": "Devre Dışı",
@@ -97,6 +104,7 @@
     "dashboard": "Genel Bakış",
     "dashboard": "Genel Bakış",
     "inbounds": "Gelenler",
     "inbounds": "Gelenler",
     "clients": "İstemciler",
     "clients": "İstemciler",
+    "groups": "Gruplar",
     "nodes": "Düğümler",
     "nodes": "Düğümler",
     "settings": "Panel Ayarları",
     "settings": "Panel Ayarları",
     "xray": "Xray Yapılandırmaları",
     "xray": "Xray Yapılandırmaları",
@@ -120,16 +128,16 @@
     },
     },
     "index": {
     "index": {
       "title": "Genel Bakış",
       "title": "Genel Bakış",
-      "cpu": "İşlemci",
+      "cpu": "CPU",
       "logicalProcessors": "Mantıksal işlemciler",
       "logicalProcessors": "Mantıksal işlemciler",
       "frequency": "Frekans",
       "frequency": "Frekans",
-      "swap": "Takas",
+      "swap": "Swap",
       "storage": "Depolama",
       "storage": "Depolama",
       "memory": "RAM",
       "memory": "RAM",
-      "threads": "İş parçacıkları",
+      "threads": "İş parçacığı",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
       "stopXray": "Durdur",
       "stopXray": "Durdur",
-      "restartXray": "Yeniden Başlat",
+      "restartXray": "Yeniden başlat",
       "xraySwitch": "Sürüm",
       "xraySwitch": "Sürüm",
       "xrayUpdates": "Xray Güncellemeleri",
       "xrayUpdates": "Xray Güncellemeleri",
       "xraySwitchClick": "Geçiş yapmak istediğiniz sürümü seçin.",
       "xraySwitchClick": "Geçiş yapmak istediğiniz sürümü seçin.",
@@ -166,7 +174,7 @@
       "toggleIpVisibility": "IP görünürlüğünü değiştir",
       "toggleIpVisibility": "IP görünürlüğünü değiştir",
       "overallSpeed": "Genel hız",
       "overallSpeed": "Genel hız",
       "upload": "Yükleme",
       "upload": "Yükleme",
-      "download": "İndirme",
+      "download": "İndir",
       "totalData": "Toplam veri",
       "totalData": "Toplam veri",
       "sent": "Gönderilen",
       "sent": "Gönderilen",
       "received": "Alınan",
       "received": "Alınan",
@@ -270,14 +278,14 @@
       },
       },
       "protocol": "Protokol",
       "protocol": "Protokol",
       "port": "Port",
       "port": "Port",
-      "portMap": "Port Atama",
+      "portMap": "Port eşlemesi",
       "traffic": "Trafik",
       "traffic": "Trafik",
       "details": "Detaylar",
       "details": "Detaylar",
       "transportConfig": "Taşıma",
       "transportConfig": "Taşıma",
       "expireDate": "Süre",
       "expireDate": "Süre",
       "createdAt": "Oluşturuldu",
       "createdAt": "Oluşturuldu",
       "updatedAt": "Güncellendi",
       "updatedAt": "Güncellendi",
-      "resetTraffic": "Trafiği Sıfırla",
+      "resetTraffic": "Trafiği sıfırla",
       "addInbound": "Gelen Ekle",
       "addInbound": "Gelen Ekle",
       "generalActions": "Genel Eylemler",
       "generalActions": "Genel Eylemler",
       "modifyInbound": "Geleni Düzenle",
       "modifyInbound": "Geleni Düzenle",
@@ -292,11 +300,29 @@
       "delAllClients": "Tüm istemcileri sil",
       "delAllClients": "Tüm istemcileri sil",
       "delAllClientsConfirmTitle": "\"{remark}\" içindeki {count} istemcinin tamamı silinsin mi?",
       "delAllClientsConfirmTitle": "\"{remark}\" içindeki {count} istemcinin tamamı silinsin mi?",
       "delAllClientsConfirmContent": "Bu inbound'a ait tüm istemcileri ve trafik kayıtlarını siler. Inbound'un kendisi korunur. Bu işlem geri alınamaz.",
       "delAllClientsConfirmContent": "Bu inbound'a ait tüm istemcileri ve trafik kayıtlarını siler. Inbound'un kendisi korunur. Bu işlem geri alınamaz.",
+      "attachClients": "İstemcileri şuna bağla…",
+      "addClientsToGroup": "İstemcileri gruba ekle…",
+      "attachClientsTitle": "«{remark}» gelenindeki istemcileri bağla",
+      "attachClientsDesc": "Aynı {count} istemciyi (aynı UUID/parola ve paylaşılan trafik) seçilen gelenlere bağlar. Bu gelende de kalırlar.",
+      "attachClientsTargets": "Hedef gelenler",
+      "attachClientsNoTargets": "Bağlanacak uyumlu başka gelen yok.",
+      "attachClientsResult": "Bağlandı {attached}, atlandı {skipped}.",
+      "attachClientsResultMixed": "Bağlandı {attached}, atlandı {skipped}, hata {errors}.",
+      "attachClientsSelectLabel": "Bağlanacak istemciler",
+      "attachClientsSearchPlaceholder": "Email veya yorum ara",
+      "attachClientsStatusDisabled": "Devre dışı",
+      "attachClientsSelectedCount": "{total} içinden {selected} seçildi",
+      "detachClients": "İstemcileri çöz",
+      "detachClientsTitle": "«{remark}» gelenindeki istemcileri çöz",
+      "detachClientsDesc": "Seçilen istemcileri yalnızca bu gelenden kaldırır. İstemci kayıtları korunur (tamamen kaldırmak için Delete kullanın). Kaynakta toplam {count} istemci var.",
+      "detachClientsResult": "Çözüldü {detached}, atlandı {skipped}.",
+      "detachClientsResultMixed": "Çözüldü {detached}, atlandı {skipped}, hata {errors}.",
+      "detachClientsSelectLabel": "Çözülecek istemciler",
       "exportLinksTitle": "Inbound bağlantılarını dışa aktar",
       "exportLinksTitle": "Inbound bağlantılarını dışa aktar",
       "exportSubsTitle": "Abonelik bağlantılarını dışa aktar",
       "exportSubsTitle": "Abonelik bağlantılarını dışa aktar",
       "exportAllLinksTitle": "Tüm inbound bağlantılarını dışa aktar",
       "exportAllLinksTitle": "Tüm inbound bağlantılarını dışa aktar",
       "exportAllSubsTitle": "Tüm abonelik bağlantılarını dışa aktar",
       "exportAllSubsTitle": "Tüm abonelik bağlantılarını dışa aktar",
-      "inboundJsonTitle": "Inbound JSON",
+      "inboundJsonTitle": "Gelen JSON",
       "deleteClient": "Müşteriyi Sil",
       "deleteClient": "Müşteriyi Sil",
       "deleteClientContent": "Müşteriyi silmek istediğinizden emin misiniz?",
       "deleteClientContent": "Müşteriyi silmek istediğinizden emin misiniz?",
       "resetTrafficContent": "Trafiği sıfırlamak istediğinizden emin misiniz?",
       "resetTrafficContent": "Trafiği sıfırlamak istediğinizden emin misiniz?",
@@ -333,7 +359,7 @@
       "delDepletedClients": "Bitmiş Müşterileri Sil",
       "delDepletedClients": "Bitmiş Müşterileri Sil",
       "delDepletedClientsTitle": "Bitmiş Müşterileri Sil",
       "delDepletedClientsTitle": "Bitmiş Müşterileri Sil",
       "delDepletedClientsContent": "Tüm bitmiş müşterileri silmek istediğinizden emin misiniz?",
       "delDepletedClientsContent": "Tüm bitmiş müşterileri silmek istediğinizden emin misiniz?",
-      "email": "E-posta",
+      "email": "Email",
       "emailDesc": "Lütfen benzersiz bir e-posta adresi sağlayın.",
       "emailDesc": "Lütfen benzersiz bir e-posta adresi sağlayın.",
       "IPLimit": "IP Limiti",
       "IPLimit": "IP Limiti",
       "IPLimitDesc": "Sayının aşılması durumunda gelen devre dışı bırakılır. (0 = devre dışı)",
       "IPLimitDesc": "Sayının aşılması durumunda gelen devre dışı bırakılır. (0 = devre dışı)",
@@ -341,7 +367,8 @@
       "IPLimitlogDesc": "IP geçmiş günlüğü. (devre dışı bırakıldıktan sonra gelini etkinleştirmek için günlüğü temizleyin)",
       "IPLimitlogDesc": "IP geçmiş günlüğü. (devre dışı bırakıldıktan sonra gelini etkinleştirmek için günlüğü temizleyin)",
       "IPLimitlogclear": "Günlüğü Temizle",
       "IPLimitlogclear": "Günlüğü Temizle",
       "setDefaultCert": "Panelden Sertifikayı Ayarla",
       "setDefaultCert": "Panelden Sertifikayı Ayarla",
-      "streamTab": "Akış",
+      "setDefaultCertEmpty": "Panel için sertifika yapılandırılmamış. Önce Ayarlar'dan ayarlayın.",
+      "streamTab": "Stream",
       "securityTab": "Güvenlik",
       "securityTab": "Güvenlik",
       "sniffingTab": "Sniffing",
       "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "Yalnızca üst veri",
       "sniffingMetadataOnly": "Yalnızca üst veri",
@@ -363,13 +390,12 @@
         "settingsHelp": "Xray settings bloğunun sarmalayıcısı:",
         "settingsHelp": "Xray settings bloğunun sarmalayıcısı:",
         "sniffing": "Sniffing",
         "sniffing": "Sniffing",
         "sniffingHelp": "Xray sniffing bloğunun sarmalayıcısı:",
         "sniffingHelp": "Xray sniffing bloğunun sarmalayıcısı:",
-        "stream": "Akış",
+        "stream": "Stream",
         "streamHelp": "Xray stream bloğunun sarmalayıcısı:",
         "streamHelp": "Xray stream bloğunun sarmalayıcısı:",
         "jsonErrorPrefix": "Gelişmiş JSON"
         "jsonErrorPrefix": "Gelişmiş JSON"
       },
       },
       "telegramDesc": "Lütfen Telegram Sohbet Kimliği sağlayın. (botta '/id' komutunu kullanın) veya ({'@'}userinfobot)",
       "telegramDesc": "Lütfen Telegram Sohbet Kimliği sağlayın. (botta '/id' komutunu kullanın) veya ({'@'}userinfobot)",
       "subscriptionDesc": "Abonelik URL'inizi bulmak için 'Detaylar'a gidin. Ayrıca, aynı adı birden fazla müşteri için kullanabilirsiniz.",
       "subscriptionDesc": "Abonelik URL'inizi bulmak için 'Detaylar'a gidin. Ayrıca, aynı adı birden fazla müşteri için kullanabilirsiniz.",
-      "info": "Bilgi",
       "same": "Aynı",
       "same": "Aynı",
       "inboundData": "Gelenin Verileri",
       "inboundData": "Gelenin Verileri",
       "exportInbound": "Geleni Dışa Aktar",
       "exportInbound": "Geleni Dışa Aktar",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "mldsa65 sertifikası alınırken hata oluştu.",
         "getNewmldsa65Error": "mldsa65 sertifikası alınırken hata oluştu.",
         "getNewVlessEncError": "VlessEnc sertifikası alınırken hata oluştu."
         "getNewVlessEncError": "VlessEnc sertifikası alınırken hata oluştu."
       },
       },
+      "form": {
+        "moveUp": "Yukarı",
+        "moveDown": "Aşağı",
+        "addAll": "Tümünü ekle",
+        "addAllFallbackTooltip": "Henüz bağlanmamış her uygun gelen için bir fallback satırı ekler",
+        "peers": "Peers",
+        "addPeer": "Peer ekle",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Yalnızca Windows. CIDR'ler eşleşen trafiğin TUN üzerinden gitmesi için sistem yönlendirme tablosuna otomatik eklenir.",
+        "autoOutboundsInterface": "Otomatik giden arabirimi",
+        "autoOutboundsInterfaceTooltip": "Giden trafiği için fiziksel arabirim. Tespit için 'auto' kullanın; Auto system routes açıkken otomatik etkinleşir.",
+        "rewriteAddress": "Adresi yeniden yaz",
+        "rewritePort": "Port'u yeniden yaz",
+        "allowedNetwork": "İzin verilen ağ",
+        "followRedirect": "Redirect'i takip et",
+        "accounts": "Hesaplar",
+        "allowTransparent": "Şeffafa izin ver",
+        "encryptionMethod": "Şifreleme yöntemi",
+        "visionTestseed": "Vision testseed",
+        "version": "Sürüm",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "Masquerade",
+        "type": "Tip",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Host'u yeniden yaz",
+        "skipTlsVerify": "TLS doğrulamayı atla",
+        "directory": "Dizin",
+        "statusCode": "Durum kodu",
+        "body": "Body",
+        "headers": "Başlıklar",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "İstek sürümü",
+        "requestMethod": "İstek yöntemi",
+        "requestPath": "İstek yolu",
+        "requestHeaders": "İstek başlıkları",
+        "responseVersion": "Yanıt sürümü",
+        "responseStatus": "Yanıt durumu",
+        "responseReason": "Yanıt sebebi",
+        "responseHeaders": "Yanıt başlıkları",
+        "heartbeatPeriod": "Heartbeat periyodu",
+        "serviceName": "Servis adı",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Maks. tamponlu yükleme",
+        "maxUploadSize": "Maks. yükleme boyutu (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Sunucu maks. başlık bayt",
+        "paddingBytes": "Padding bayt",
+        "uplinkHttpMethod": "Uplink HTTP yöntemi",
+        "paddingObfsMode": "Padding obfs modu",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding konumu",
+        "paddingMethod": "Padding yöntemi",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "SSE başlığı yok",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Yükleme (MB/s)",
+        "downlinkMbps": "İndirme (MB/s)",
+        "cwndMultiplier": "CWND çarpanı",
+        "maxSendingWindow": "Maks. gönderme penceresi",
+        "externalProxy": "Harici proxy",
+        "sniPlaceholder": "SNI (varsayılan host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Varsayılan",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Yalnızca V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "Güvenilir X-Forwarded-For",
+        "addressPortStrategy": "Adres+port stratejisi",
+        "tryDelayMs": "Deneme gecikmesi (ms)",
+        "prioritizeIPv6": "IPv6 önceliği",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Maks. eş zamanlı deneme",
+        "customSockopt": "Özel sockopt",
+        "addCustomOption": "Özel seçenek ekle",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Otomatik",
+        "minMaxVersion": "Min/Maks sürüm",
+        "rejectUnknownSni": "Bilinmeyen SNI reddet",
+        "disableSystemRoot": "System Root'u devre dışı bırak",
+        "sessionResumption": "Oturum sürdürme",
+        "oneTimeLoading": "Tek seferlik yükleme",
+        "usageOption": "Kullanım seçeneği",
+        "buildChain": "Zincir oluştur",
+        "echKey": "ECH key",
+        "echConfig": "ECH yapılandırması",
+        "getNewEchCert": "Yeni ECH sertifikası al",
+        "show": "Göster",
+        "xver": "Xver",
+        "target": "Hedef",
+        "maxTimeDiff": "Maks. zaman farkı (ms)",
+        "minClientVer": "Min. istemci sürümü",
+        "maxClientVer": "Maks. istemci sürümü",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Yeni sertifika al",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Yeni Seed al"
+      },
+      "info": {
+        "mode": "Mod",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Arabirim adı",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Giden arabirimi",
+        "autoSystemRoutes": "Otomatik sistem yönlendirmeleri",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "Çekirdeksiz TUN",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Peer {n} yapılandırması"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "İstek",
           "request": "İstek",
@@ -456,6 +615,20 @@
       "days": "Gün",
       "days": "Gün",
       "renew": "Otomatik yenileme",
       "renew": "Otomatik yenileme",
       "renewDesc": "Süre dolduktan sonra otomatik yenileme. (0 = devre dışı) (birim: gün)",
       "renewDesc": "Süre dolduktan sonra otomatik yenileme. (0 = devre dışı) (birim: gün)",
+      "searchPlaceholder": "Email, yorum, sub ID, UUID, parola, auth ara…",
+      "filterTitle": "İstemcileri filtrele",
+      "clearAllFilters": "Tümünü temizle",
+      "sortOldest": "Önce en eski",
+      "sortNewest": "Önce en yeni",
+      "sortRecentlyUpdated": "Son güncellenen",
+      "sortRecentlyOnline": "Son zamanlarda çevrimiçi",
+      "sortEmailAZ": "Email A→Z",
+      "sortEmailZA": "Email Z→A",
+      "sortMostTraffic": "En çok trafik",
+      "sortHighestRemaining": "En çok kalan",
+      "sortExpiringSoonest": "Yakında biten",
+      "has": "Var",
+      "hasNot": "Yok",
       "title": "İstemciler",
       "title": "İstemciler",
       "actions": "Eylemler",
       "actions": "Eylemler",
       "totalGB": "Toplam Gönderilen/Alınan (GB)",
       "totalGB": "Toplam Gönderilen/Alınan (GB)",
@@ -465,7 +638,10 @@
       "password": "Şifre",
       "password": "Şifre",
       "subId": "Abonelik ID'si",
       "subId": "Abonelik ID'si",
       "online": "Çevrimiçi",
       "online": "Çevrimiçi",
-      "email": "E-posta",
+      "email": "Email",
+      "group": "Grup",
+      "groupDesc": "İlgili istemcileri gruplamak için mantıksal etiket (ekip, müşteri, bölge). Araç çubuğundan filtrelenebilir.",
+      "groupPlaceholder": "örn. customer-a",
       "comment": "Yorum",
       "comment": "Yorum",
       "traffic": "Trafik",
       "traffic": "Trafik",
       "offline": "Çevrimdışı",
       "offline": "Çevrimdışı",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Tüm istemcilerin trafiğini sıfırla",
       "resetAllTraffics": "Tüm istemcilerin trafiğini sıfırla",
       "resetAllTrafficsTitle": "Tüm istemcilerin trafiği sıfırlansın mı?",
       "resetAllTrafficsTitle": "Tüm istemcilerin trafiği sıfırlansın mı?",
       "resetAllTrafficsContent": "Her istemcinin yükleme/indirme sayaçları sıfırlanır. Kotalar ve son kullanma tarihleri etkilenmez. Geri alınamaz.",
       "resetAllTrafficsContent": "Her istemcinin yükleme/indirme sayaçları sıfırlanır. Kotalar ve son kullanma tarihleri etkilenmez. Geri alınamaz.",
-      "empty": "Henüz istemci yok — başlamak için bir tane ekleyin.",
       "deleteConfirmTitle": "{email} istemcisi silinsin mi?",
       "deleteConfirmTitle": "{email} istemcisi silinsin mi?",
       "deleteConfirmContent": "Bu işlem istemciyi bağlı tüm inbound'lardan kaldırır ve trafik kaydını siler. Geri alınamaz.",
       "deleteConfirmContent": "Bu işlem istemciyi bağlı tüm inbound'lardan kaldırır ve trafik kaydını siler. Geri alınamaz.",
       "deleteSelected": "Sil ({count})",
       "deleteSelected": "Sil ({count})",
       "adjustSelected": "Ayarla ({count})",
       "adjustSelected": "Ayarla ({count})",
+      "subLinksSelected": "Abonelik bağlantıları ({count})",
+      "addToGroupTitle": "{count} istemciyi bir gruba ekle",
+      "addToGroupTooltip": "Mevcut bir grubu seçin veya yeni ad girin. İstemcileri mevcut gruplarından çıkarmak için Ungroup'u kullanın.",
+      "addToGroupPlaceholder": "Grup adı",
+      "addToGroupSuccessToast": "{count} istemci {group} grubuna eklendi",
+      "ungroupSuccessToast": "{count} istemcinin grubu temizlendi",
+      "ungroup": "Gruptan çıkar",
+      "ungroupConfirmTitle": "{count} istemciyi gruptan çıkar?",
+      "ungroupConfirmContent": "Seçilen her istemcinin grup etiketini temizler. İstemciler korunur (tamamen kaldırmak için Delete kullanın).",
+      "addToGroup": "Gruba ekle",
+      "attach": "Bağla",
+      "adjust": "Ayarla",
+      "subLinks": "Abonelik bağlantıları",
+      "selectedCount": "{count} seçildi",
+      "attachSelected": "Bağla ({count})",
+      "attachToInboundsTitle": "{count} istemciyi gelen(ler)e bağla",
+      "attachToInboundsDesc": "Seçilen {count} istemciyi (aynı UUID/parola ve paylaşılan trafik) seçilen gelene bağlar. Mevcut bağlantılar korunur.",
+      "attachToInboundsTargets": "Hedef gelenler",
+      "attachToInboundsNoTargets": "Bağlanacak çoklu kullanıcılı gelen yok.",
+      "detachSelected": "Çöz ({count})",
+      "detach": "Çöz",
+      "detachFromInboundsTitle": "{count} istemciyi gelen(ler)den çöz",
+      "detachFromInboundsDesc": "Seçilen {count} istemciyi seçilen gelenden kaldırır. İstemcinin bağlı olmadığı çiftler sessizce atlanır. İstemci kayıtları korunur (tamamen kaldırmak için Delete kullanın).",
+      "detachFromInboundsTargets": "Çözülecek gelenler",
+      "detachFromInboundsNoTargets": "Çoklu kullanıcılı gelen yok.",
+      "detachFromInboundsResult": "Çözüldü {detached}, atlandı {skipped}.",
+      "detachFromInboundsResultMixed": "Çözüldü {detached}, atlandı {skipped}, hata {errors}.",
+      "subLinksTitle": "Abonelik bağlantıları ({count})",
+      "subLinkColumn": "Abonelik URL",
+      "subJsonLinkColumn": "Abonelik JSON URL",
+      "subLinksCopyAll": "Tümünü kopyala",
+      "subLinksCopiedAll": "{count} bağlantı kopyalandı",
+      "subLinksEmpty": "Seçilen istemcilerin hiçbirinin abonelik ID'si yok.",
+      "subLinksDisabled": "Abonelik hizmeti devre dışı.",
+      "subLinksDisabledHint": "Bağlantı oluşturmak için Panel Ayarları → Abonelik'ten etkinleştirin.",
       "bulkDeleteConfirmTitle": "{count} istemci silinsin mi?",
       "bulkDeleteConfirmTitle": "{count} istemci silinsin mi?",
       "bulkDeleteConfirmContent": "Seçili her istemci bağlı tüm inbound'lardan kaldırılır ve trafik kaydı silinir. Geri alınamaz.",
       "bulkDeleteConfirmContent": "Seçili her istemci bağlı tüm inbound'lardan kaldırılır ve trafik kaydı silinir. Geri alınamaz.",
       "bulkAdjustTitle": "{count} istemciyi ayarla",
       "bulkAdjustTitle": "{count} istemciyi ayarla",
@@ -508,6 +718,7 @@
       "hysteriaAuth": "Hysteria Auth",
       "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
+      "vmessSecurity": "VMess Güvenlik",
       "reverseTag": "Reverse tag",
       "reverseTag": "Reverse tag",
       "reverseTagPlaceholder": "İsteğe bağlı Reverse tag",
       "reverseTagPlaceholder": "İsteğe bağlı Reverse tag",
       "telegramId": "Telegram kullanıcı ID'si",
       "telegramId": "Telegram kullanıcı ID'si",
@@ -528,10 +739,48 @@
         "delDepleted": "{count} tükenmiş istemci silindi"
         "delDepleted": "{count} tükenmiş istemci silindi"
       }
       }
     },
     },
+    "groups": {
+      "title": "Gruplar",
+      "name": "İsim",
+      "clientCount": "Gruptaki istemciler",
+      "totalGroups": "Toplam grup",
+      "totalGroupedClients": "Grubu olan istemciler",
+      "emptyGroups": "Boş gruplar",
+      "addGroup": "Grup ekle",
+      "createSuccess": "«{name}» grubu oluşturuldu.",
+      "rename": "Yeniden adlandır",
+      "renameTitle": "{name} yeniden adlandır",
+      "renameCollision": "«{name}» adında bir grup zaten var.",
+      "renameSuccess": "{count} istemcinin grubu yeniden adlandırıldı.",
+      "deleteConfirmTitle": "{name} grubunu sil?",
+      "deleteConfirmContent": "Bu, grubu siler ve etiketini {count} istemciden temizler. İstemciler silinmez.",
+      "deleteSuccess": "{count} istemcinin grubu temizlendi.",
+      "resetTraffic": "Trafiği sıfırla",
+      "resetConfirmTitle": "{name} grubunun trafiğini sıfırla?",
+      "resetConfirmContent": "Bu, bu gruptaki tüm {count} istemcinin yukarı/aşağı trafiğini sıfırlar.",
+      "resetSuccess": "{count} istemcinin trafiği sıfırlandı.",
+      "adjustSuccess": "{name} içinde {count} istemci ayarlandı.",
+      "emptyForAction": "Bu grupta henüz istemci yok.",
+      "deleteGroupOnly": "Grubu sil (istemcileri tut)",
+      "deleteClients": "Gruptaki istemcileri sil",
+      "deleteClientsConfirmTitle": "{name} içindeki tüm istemcileri sil?",
+      "deleteClientsConfirmContent": "Bu, {count} istemciyi trafik kayıtlarıyla birlikte kalıcı olarak siler. Grup etiketi de temizlenir. Geri alınamaz.",
+      "deleteClientsSuccess": "{count} istemci silindi.",
+      "deleteClientsMixed": "{ok} silindi, {failed} atlandı",
+      "addToGroup": "İstemci ekle…",
+      "addToGroupTitle": "«{name}» grubuna istemci ekle",
+      "addToGroupDesc": "Bu gruba eklemek için istemcileri seçin. Mevcut gelen bağlantıları korunur; yalnızca grup etiketi değişir. Halihazırda bu grupta olan istemciler listelenmez.",
+      "addToGroupEmpty": "Eklenecek başka istemci yok.",
+      "addToGroupResult": "{count} istemci {name} grubuna eklendi.",
+      "removeFromGroup": "İstemci çıkar…",
+      "removeFromGroupTitle": "«{name}» grubundan istemci çıkar",
+      "removeFromGroupDesc": "Bu gruptan çıkarılacak üyeleri seçin. İstemciler korunur (tamamen kaldırmak için «Gruptaki istemcileri sil» kullanın).",
+      "removeFromGroupResult": "{name} grubundan {count} istemci çıkarıldı."
+    },
     "nodes": {
     "nodes": {
       "title": "Düğümler",
       "title": "Düğümler",
       "addNode": "Düğüm Ekle",
       "addNode": "Düğüm Ekle",
-      "editNode": "Düğümü Düzenle",
+      "editNode": "Düğümü düzenle",
       "totalNodes": "Toplam Düğüm",
       "totalNodes": "Toplam Düğüm",
       "onlineNodes": "Çevrimiçi",
       "onlineNodes": "Çevrimiçi",
       "offlineNodes": "Çevrimdışı",
       "offlineNodes": "Çevrimdışı",
@@ -543,7 +792,7 @@
       "scheme": "Şema",
       "scheme": "Şema",
       "address": "Adres",
       "address": "Adres",
       "port": "Port",
       "port": "Port",
-      "basePath": "Temel Yol",
+      "basePath": "Base Path",
       "apiToken": "API Token",
       "apiToken": "API Token",
       "apiTokenPlaceholder": "Uzak panelin Ayarlar sayfasındaki token",
       "apiTokenPlaceholder": "Uzak panelin Ayarlar sayfasındaki token",
       "apiTokenHint": "Uzak panel API token'ını Ayarlar → API Token altında gösterir.",
       "apiTokenHint": "Uzak panel API token'ını Ayarlar → API Token altında gösterir.",
@@ -555,7 +804,7 @@
       "status": "Durum",
       "status": "Durum",
       "cpu": "CPU",
       "cpu": "CPU",
       "mem": "Bellek",
       "mem": "Bellek",
-      "uptime": "Çalışma Süresi",
+      "uptime": "Çalışma süresi",
       "latency": "Gecikme",
       "latency": "Gecikme",
       "lastHeartbeat": "Son Sinyal",
       "lastHeartbeat": "Son Sinyal",
       "xrayVersion": "Xray Sürümü",
       "xrayVersion": "Xray Sürümü",
@@ -590,7 +839,7 @@
       "title": "Panel Ayarları",
       "title": "Panel Ayarları",
       "save": "Kaydet",
       "save": "Kaydet",
       "infoDesc": "Burada yapılan her değişikliğin kaydedilmesi gerekir. Değişikliklerin uygulanması için paneli yeniden başlatın.",
       "infoDesc": "Burada yapılan her değişikliğin kaydedilmesi gerekir. Değişikliklerin uygulanması için paneli yeniden başlatın.",
-      "restartPanel": "Paneli Yeniden Başlat",
+      "restartPanel": "Paneli yeniden başlat",
       "restartPanelDesc": "Paneli yeniden başlatmak istediğinizden emin misiniz? Yeniden başlattıktan sonra panele erişemezseniz, sunucudaki panel günlük bilgilerini görüntüleyin.",
       "restartPanelDesc": "Paneli yeniden başlatmak istediğinizden emin misiniz? Yeniden başlattıktan sonra panele erişemezseniz, sunucudaki panel günlük bilgilerini görüntüleyin.",
       "restartPanelSuccess": "Panel başarıyla yeniden başlatıldı",
       "restartPanelSuccess": "Panel başarıyla yeniden başlatıldı",
       "actions": "Eylemler",
       "actions": "Eylemler",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Web paneli için genel anahtar dosya yolu. ('/' ile başlar)",
       "publicKeyPathDesc": "Web paneli için genel anahtar dosya yolu. ('/' ile başlar)",
       "privateKeyPath": "Özel Anahtar Yolu",
       "privateKeyPath": "Özel Anahtar Yolu",
       "privateKeyPathDesc": "Web paneli için özel anahtar dosya yolu. ('/' ile başlar)",
       "privateKeyPathDesc": "Web paneli için özel anahtar dosya yolu. ('/' ile başlar)",
-      "panelUrlPath": "URI Yolu",
+      "panelUrlPath": "URI yolu",
       "panelUrlPathDesc": "Web paneli için URI yolu. ('/' ile başlar ve '/' ile biter)",
       "panelUrlPathDesc": "Web paneli için URI yolu. ('/' ile başlar ve '/' ile biter)",
       "pageSize": "Sayfa Boyutu",
       "pageSize": "Sayfa Boyutu",
       "pageSizeDesc": "Gelenler tablosu için sayfa boyutunu belirleyin. (0 = devre dışı)",
       "pageSizeDesc": "Gelenler tablosu için sayfa boyutunu belirleyin. (0 = devre dışı)",
+      "panelProxy": "Panel ağ proxy'si",
+      "panelProxyDesc": "Panelin kendi giden istekleri (geo güncellemeleri, Xray/panel sürüm kontrolleri, Telegram) bu proxy üzerinden yönlendirir; sunucu tarafındaki GitHub/Telegram filtrelemesini atlatmak için. socks5:// veya http(s):// kabul eder, örn. yerel bir Xray SOCKS geleni. Doğrudan bağlantı için boş bırakın.",
       "remarkModel": "Açıklama Modeli & Ayırma Karakteri",
       "remarkModel": "Açıklama Modeli & Ayırma Karakteri",
       "datepicker": "Takvim Türü",
       "datepicker": "Takvim Türü",
       "datepickerPlaceholder": "Tarih Seçin",
       "datepickerPlaceholder": "Tarih Seçin",
@@ -634,7 +885,7 @@
       "telegramTokenDesc": "'{'@'}BotFather'dan alınan Telegram bot token.",
       "telegramTokenDesc": "'{'@'}BotFather'dan alınan Telegram bot token.",
       "telegramProxy": "SOCKS Proxy",
       "telegramProxy": "SOCKS Proxy",
       "telegramProxyDesc": "Telegram'a bağlanmak için SOCKS5 proxy'sini etkinleştirir. (ayarları kılavuzda belirtilen şekilde ayarlayın)",
       "telegramProxyDesc": "Telegram'a bağlanmak için SOCKS5 proxy'sini etkinleştirir. (ayarları kılavuzda belirtilen şekilde ayarlayın)",
-      "telegramAPIServer": "Telegram API Server",
+      "telegramAPIServer": "Telegram API Sunucusu",
       "telegramAPIServerDesc": "Kullanılacak Telegram API sunucusu. Varsayılan sunucuyu kullanmak için boş bırakın.",
       "telegramAPIServerDesc": "Kullanılacak Telegram API sunucusu. Varsayılan sunucuyu kullanmak için boş bırakın.",
       "telegramChatId": "Yönetici Sohbet Kimliği",
       "telegramChatId": "Yönetici Sohbet Kimliği",
       "telegramChatIdDesc": "Telegram Yönetici Sohbet Kimliği(leri). (virgülle ayrılmış)(buradan alın {'@'}userinfobot) veya (botta '/id' komutunu kullanın)",
       "telegramChatIdDesc": "Telegram Yönetici Sohbet Kimliği(leri). (virgülle ayrılmış)(buradan alın {'@'}userinfobot) veya (botta '/id' komutunu kullanın)",
@@ -658,6 +909,8 @@
       "subEnable": "Abonelik Hizmetini Etkinleştir",
       "subEnable": "Abonelik Hizmetini Etkinleştir",
       "subEnableDesc": "Abonelik hizmetini etkinleştirir.",
       "subEnableDesc": "Abonelik hizmetini etkinleştirir.",
       "subJsonEnable": "JSON abonelik uç noktasını bağımsız olarak Etkinleştir/Devre Dışı bırak.",
       "subJsonEnable": "JSON abonelik uç noktasını bağımsız olarak Etkinleştir/Devre Dışı bırak.",
+      "subJsonEnableTitle": "JSON aboneliği",
+      "subClashEnableTitle": "Clash / Mihomo aboneliği",
       "subTitle": "Abonelik Başlığı",
       "subTitle": "Abonelik Başlığı",
       "subTitleDesc": "VPN istemcisinde gösterilen başlık",
       "subTitleDesc": "VPN istemcisinde gösterilen başlık",
       "subSupportUrl": "Destek URL'si",
       "subSupportUrl": "Destek URL'si",
@@ -678,13 +931,13 @@
       "subCertPathDesc": "Abonelik hizmeti için genel anahtar dosya yolu. ('/' ile başlar)",
       "subCertPathDesc": "Abonelik hizmeti için genel anahtar dosya yolu. ('/' ile başlar)",
       "subKeyPath": "Özel Anahtar Yolu",
       "subKeyPath": "Özel Anahtar Yolu",
       "subKeyPathDesc": "Abonelik hizmeti için özel anahtar dosya yolu. ('/' ile başlar)",
       "subKeyPathDesc": "Abonelik hizmeti için özel anahtar dosya yolu. ('/' ile başlar)",
-      "subPath": "URI Yolu",
+      "subPath": "URI yolu",
       "subPathDesc": "Abonelik hizmeti için URI yolu. ('/' ile başlar ve '/' ile biter)",
       "subPathDesc": "Abonelik hizmeti için URI yolu. ('/' ile başlar ve '/' ile biter)",
       "subDomain": "Dinleme Alan Adı",
       "subDomain": "Dinleme Alan Adı",
       "subDomainDesc": "Abonelik hizmeti için alan adı. (tüm alan adlarını ve IP'leri dinlemek için boş bırakın)",
       "subDomainDesc": "Abonelik hizmeti için alan adı. (tüm alan adlarını ve IP'leri dinlemek için boş bırakın)",
       "subUpdates": "Güncelleme Aralıkları",
       "subUpdates": "Güncelleme Aralıkları",
       "subUpdatesDesc": "Müşteri uygulamalarındaki abonelik URL'sinin güncelleme aralıkları. (birim: saat)",
       "subUpdatesDesc": "Müşteri uygulamalarındaki abonelik URL'sinin güncelleme aralıkları. (birim: saat)",
-      "subEncrypt": "Şifrele",
+      "subEncrypt": "Kodla",
       "subEncryptDesc": "Abonelik hizmetinin döndürülen içeriği Base64 ile şifrelenir.",
       "subEncryptDesc": "Abonelik hizmetinin döndürülen içeriği Base64 ile şifrelenir.",
       "subShowInfo": "Kullanım Bilgisini Göster",
       "subShowInfo": "Kullanım Bilgisini Göster",
       "subShowInfoDesc": "Kalan trafik ve tarih müşteri uygulamalarında görüntülenir.",
       "subShowInfoDesc": "Kalan trafik ve tarih müşteri uygulamalarında görüntülenir.",
@@ -693,7 +946,7 @@
       "subURI": "Ters Proxy URI",
       "subURI": "Ters Proxy URI",
       "subURIDesc": "Proxy arkasında kullanılacak abonelik URL'sinin URI yolu.",
       "subURIDesc": "Proxy arkasında kullanılacak abonelik URL'sinin URI yolu.",
       "externalTrafficInformEnable": "Harici Trafik Bilgisi",
       "externalTrafficInformEnable": "Harici Trafik Bilgisi",
-      "externalTrafficInformEnableDesc": "Her trafik güncellemesinde harici API'yi bilgilendirin.",
+      "externalTrafficInformEnableDesc": "Her trafik güncellemesinde harici API'yi bilgilendir.",
       "externalTrafficInformURI": "Harici Trafik Bilgisi URI'si",
       "externalTrafficInformURI": "Harici Trafik Bilgisi URI'si",
       "externalTrafficInformURIDesc": "Trafik güncellemeleri bu URI'ye gönderildi.",
       "externalTrafficInformURIDesc": "Trafik güncellemeleri bu URI'ye gönderildi.",
       "restartXrayOnClientDisable": "Otomatik Devre Dışı Sonrası Xray'i Yeniden Başlat",
       "restartXrayOnClientDisable": "Otomatik Devre Dışı Sonrası Xray'i Yeniden Başlat",
@@ -703,6 +956,54 @@
       "fragmentSett": "Parçalama Ayarları",
       "fragmentSett": "Parçalama Ayarları",
       "noisesDesc": "Noises'i Etkinleştir.",
       "noisesDesc": "Noises'i Etkinleştir.",
       "noisesSett": "Noises Ayarları",
       "noisesSett": "Noises Ayarları",
+      "trustedProxyCidrs": "Güvenilir proxy CIDR'leri",
+      "trustedProxyCidrsDesc": "İletilen host, proto ve istemci IP başlıklarını ayarlamasına izin verilen IP'ler/CIDR'ler (virgülle ayrılmış).",
+      "ldap": {
+        "enable": "LDAP senkronizasyonunu etkinleştir",
+        "host": "LDAP host",
+        "port": "LDAP port",
+        "useTls": "TLS kullan (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Yapılandırıldı; mevcut parolayı korumak için boş bırakın.",
+        "passwordUnconfigured": "Yapılandırılmadı.",
+        "passwordPlaceholder": "Yapılandırıldı — değiştirmek için yeni değer girin",
+        "baseDn": "Base DN",
+        "userFilter": "Kullanıcı filtresi",
+        "userAttr": "Kullanıcı özniteliği (username/email)",
+        "vlessField": "VLESS flag özniteliği",
+        "flagField": "Genel flag özniteliği (opsiyonel)",
+        "flagFieldDesc": "Ayarlanırsa VLESS flag'ini geçersiz kılar — örn. shadowInactive.",
+        "truthyValues": "Truthy değerler",
+        "truthyValuesDesc": "Virgülle ayrılmış; varsayılan: true,1,yes,on",
+        "invertFlag": "Flag'i tersine çevir",
+        "invertFlagDesc": "Öznitelik «devre dışı» anlamına geldiğinde etkinleştirin (örn. shadowInactive).",
+        "syncSchedule": "Senkronizasyon programı",
+        "syncScheduleDesc": "cron benzeri dize, örn. @every 1m",
+        "inboundTags": "Gelen etiketleri",
+        "inboundTagsDesc": "LDAP senkronizasyonunun istemci otomatik oluşturup/silebileceği gelenler.",
+        "noInbounds": "Gelen bulunamadı. Önce Gelenler'de bir tane oluşturun.",
+        "autoCreate": "İstemcileri otomatik oluştur",
+        "autoDelete": "İstemcileri otomatik sil",
+        "defaultTotalGb": "Varsayılan toplam (GB)",
+        "defaultExpiryDays": "Varsayılan son kullanma (gün)",
+        "defaultIpLimit": "Varsayılan IP limiti"
+      },
+      "subFormats": {
+        "packets": "Paketler",
+        "length": "Uzunluk",
+        "interval": "Aralık",
+        "maxSplit": "Maks. bölünme",
+        "noises": "Gürültüler",
+        "noiseItem": "Gürültü №{n}",
+        "type": "Tip",
+        "packet": "Paket",
+        "delayMs": "Gecikme (ms)",
+        "applyTo": "Şuna uygula",
+        "addNoise": "+ Gürültü",
+        "concurrency": "Eşzamanlılık",
+        "xudpConcurrency": "xudp eşzamanlılık",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir.",
       "muxDesc": "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir.",
       "muxSett": "Mux Ayarları",
       "muxSett": "Mux Ayarları",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "Xray Yapılandırmaları",
       "title": "Xray Yapılandırmaları",
       "save": "Kaydet",
       "save": "Kaydet",
-      "restart": "Xray'i Yeniden Başlat",
+      "restart": "Xray'i yeniden başlat",
       "restartSuccess": "Xray başarıyla yeniden başlatıldı",
       "restartSuccess": "Xray başarıyla yeniden başlatıldı",
+      "restartOutputTitle": "Xray yeniden başlatma çıktısı",
+      "restartConfirmTitle": "Xray'i yeniden başlat?",
+      "restartConfirmContent": "Xray hizmeti kaydedilmiş yapılandırma ile yeniden yüklenir.",
       "stopSuccess": "Xray başarıyla durduruldu",
       "stopSuccess": "Xray başarıyla durduruldu",
       "restartError": "Xray yeniden başlatılırken bir hata oluştu.",
       "restartError": "Xray yeniden başlatılırken bir hata oluştu.",
       "stopError": "Xray durdurulurken bir hata oluştu.",
       "stopError": "Xray durdurulurken bir hata oluştu.",
@@ -794,6 +1098,8 @@
       "InboundsDesc": "Belirli müşterileri kabul eder.",
       "InboundsDesc": "Belirli müşterileri kabul eder.",
       "Outbounds": "Gidenler",
       "Outbounds": "Gidenler",
       "Balancers": "Dengeler",
       "Balancers": "Dengeler",
+      "balancerTagRequired": "Etiket gereklidir",
+      "balancerSelectorRequired": "En az bir giden seçin",
       "OutboundsDesc": "Giden trafiğin yolunu ayarlayın.",
       "OutboundsDesc": "Giden trafiğin yolunu ayarlayın.",
       "Routings": "Yönlendirme Kuralları",
       "Routings": "Yönlendirme Kuralları",
       "RoutingsDesc": "Her kuralın önceliği önemlidir!",
       "RoutingsDesc": "Her kuralın önceliği önemlidir!",
@@ -832,6 +1138,73 @@
         "edit": "Kuralı Düzenle",
         "edit": "Kuralı Düzenle",
         "useComma": "Virgülle ayrılmış öğeler"
         "useComma": "Virgülle ayrılmış öğeler"
       },
       },
+      "routing": {
+        "dragToReorder": "Yeniden sıralamak için sürükleyin"
+      },
+      "ruleForm": {
+        "sourceIps": "Kaynak IP'ler",
+        "sourcePort": "Kaynak port",
+        "vlessRoute": "VLESS rotası",
+        "attributes": "Öznitelikler",
+        "value": "Değer",
+        "user": "Kullanıcı",
+        "inboundTags": "Gelen etiketleri",
+        "outboundTag": "Giden etiketi",
+        "balancerTag": "Dengeleyici etiketi",
+        "balancerTagTooltip": "Trafiği yapılandırılmış yük dengeleyicilerden biri üzerinden yönlendirir"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Etiket başka bir giden tarafından kullanılıyor",
+        "tagRequired": "Etiket gereklidir",
+        "tagPlaceholder": "benzersiz-etiket",
+        "localIpPlaceholder": "yerel IP",
+        "addressRequired": "Adres gereklidir",
+        "portRequired": "Port gereklidir",
+        "optional": "opsiyonel",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "UoT sürümü",
+        "inboundTag": "Gelen etiketi",
+        "inboundTagPlaceholder": "yönlendirme kurallarında kullanılan gelen etiketi",
+        "responseType": "Yanıt tipi",
+        "rewriteNetwork": "Ağı yeniden yaz",
+        "unchanged": "(değişmedi)",
+        "unchangedAddress": "(değişmedi) örn. 1.1.1.1",
+        "rules": "Kurallar",
+        "ruleN": "Kural {n}",
+        "action": "Eylem",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Nihai kurallar",
+        "overrideXrayPrivateIp": "Xray'in varsayılan özel IP bloğunu geçersiz kıl",
+        "blockDelay": "Engelleme gecikmesi (ms)",
+        "reverseSniffing": "Ters sniffing",
+        "workers": "Workers",
+        "reserved": "Ayrılmış",
+        "minUploadInterval": "Min. yükleme aralığı (ms)",
+        "maxUploadSizeBytes": "Maks. yükleme boyutu (bayt)",
+        "uplinkChunkSize": "Uplink chunk boyutu",
+        "noGrpcHeader": "gRPC başlığı yok",
+        "maxConcurrency": "Maks. eşzamanlılık",
+        "maxConnections": "Maks. bağlantı",
+        "maxReuseTimes": "Maks. yeniden kullanım",
+        "maxRequestTimes": "Maks. istek sayısı",
+        "maxReusableSecs": "Maks. yeniden kullanılabilir saniye",
+        "keepAlivePeriod": "Keep alive periyodu",
+        "authPassword": "Auth parolası",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "sunucu adı",
+        "verifyPeerName": "Peer adını doğrula",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Keep alive aralığı",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Arabirim",
+        "ipv6Only": "Yalnızca IPv6",
+        "acceptProxyProtocol": "Proxy protocol kabul et",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Giden Ekle",
         "addOutbound": "Giden Ekle",
         "addReverse": "Ters Ekle",
         "addReverse": "Ters Ekle",
@@ -844,9 +1217,9 @@
         "tagDesc": "Benzersiz Etiket",
         "tagDesc": "Benzersiz Etiket",
         "address": "Adres",
         "address": "Adres",
         "reverse": "Ters",
         "reverse": "Ters",
-        "domain": "Alan Adı",
+        "domain": "Alan adı",
         "type": "Tür",
         "type": "Tür",
-        "bridge": "Köprü",
+        "bridge": "Bridge",
         "portal": "Portal",
         "portal": "Portal",
         "link": "Bağlantı",
         "link": "Bağlantı",
         "intercon": "Bağlantı",
         "intercon": "Bağlantı",
@@ -860,6 +1233,8 @@
         "testSuccess": "Test başarılı",
         "testSuccess": "Test başarılı",
         "testFailed": "Test başarısız",
         "testFailed": "Test başarısız",
         "testError": "Giden test edilemedi",
         "testError": "Giden test edilemedi",
+        "testModeTooltip": "TCP: hızlı dial-only probe. HTTP: xray üzerinden tam istek.",
+        "testAll": "Tümünü test et",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Erişim Jetonu",
         "accessToken": "Erişim Jetonu",
         "country": "Ülke",
         "country": "Ülke",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "Seçiciler",
         "balancerSelectors": "Seçiciler",
         "tag": "Etiket",
         "tag": "Etiket",
         "tagDesc": "Benzersiz Etiket",
         "tagDesc": "Benzersiz Etiket",
+        "tagDuplicate": "Etiket başka bir dengeleyici tarafından kullanılıyor",
+        "tagPlaceholder": "benzersiz dengeleyici etiketi",
+        "selector": "Seçici",
+        "fallback": "Fallback",
+        "expected": "Beklenen",
+        "expectedPlaceholder": "optimal düğüm sayısı",
+        "maxRtt": "Maks. RTT",
+        "tolerance": "Tolerans",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "Dengeleyici Etiketi ve Giden Etiketi aynı anda kullanılamaz. Aynı anda kullanıldığında yalnızca giden etiketi çalışır."
         "balancerDesc": "Dengeleyici Etiketi ve Giden Etiketi aynı anda kullanılamaz. Aynı anda kullanıldığında yalnızca giden etiketi çalışır."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Kullanıcı Seviyesi",
         "userLevel": "Kullanıcı Seviyesi",
         "userLevelDesc": "Bu giriş yoluyla yapılan tüm bağlantılar bu kullanıcı seviyesini kullanacaktır. Varsayılan değer 0'dır"
         "userLevelDesc": "Bu giriş yoluyla yapılan tüm bağlantılar bu kullanıcı seviyesini kullanacaktır. Varsayılan değer 0'dır"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Özel anahtar",
+        "noServers": "Seçilen ülke için sunucu bulunamadı",
+        "noPublicKey": "Seçilen sunucu NordLynx genel anahtarı yayınlamıyor.",
+        "outboundAdded": "NordVPN giden eklendi",
+        "outboundUpdated": "NordVPN giden güncellendi"
+      },
+      "warp": {
+        "licenseError": "WARP lisansı ayarlanamadı.",
+        "fetchFirst": "Önce WARP yapılandırmasını alın.",
+        "createAccount": "WARP hesabı oluştur",
+        "accessToken": "Access token",
+        "deviceId": "Cihaz ID",
+        "licenseKey": "Lisans anahtarı",
+        "privateKey": "Özel anahtar",
+        "deleteAccount": "Hesabı sil",
+        "settings": "Ayarlar",
+        "licenseKeyLabel": "WARP / WARP+ lisans anahtarı",
+        "key": "Anahtar",
+        "keyPlaceholder": "26 karakterli WARP+ anahtarı",
+        "accountInfo": "Hesap bilgisi",
+        "deviceName": "Cihaz adı",
+        "deviceModel": "Cihaz modeli",
+        "deviceEnabled": "Cihaz etkin",
+        "accountType": "Hesap tipi",
+        "role": "Rol",
+        "warpPlusData": "WARP+ veri",
+        "quota": "Kota",
+        "usage": "Kullanım",
+        "addOutbound": "Giden ekle"
+      },
       "dns": {
       "dns": {
         "enable": "DNS'yi Etkinleştir",
         "enable": "DNS'yi Etkinleştir",
         "enableDesc": "Dahili DNS sunucusunu etkinleştir",
         "enableDesc": "Dahili DNS sunucusunu etkinleştir",
@@ -911,7 +1328,7 @@
         "strategyDesc": "Alan adlarını çözmek için genel strateji",
         "strategyDesc": "Alan adlarını çözmek için genel strateji",
         "add": "Sunucu Ekle",
         "add": "Sunucu Ekle",
         "edit": "Sunucuyu Düzenle",
         "edit": "Sunucuyu Düzenle",
-        "domains": "Alan Adları",
+        "domains": "Alan adları",
         "expectIPs": "Beklenen IP'ler",
         "expectIPs": "Beklenen IP'ler",
         "unexpectIPs": "Beklenmeyen IP'ler",
         "unexpectIPs": "Beklenmeyen IP'ler",
         "useSystemHosts": "Sistem Hosts'larını Kullan",
         "useSystemHosts": "Sistem Hosts'larını Kullan",
@@ -992,7 +1409,7 @@
       "2faFailed": "2FA Hatası",
       "2faFailed": "2FA Hatası",
       "report": "🕰 Planlanmış Raporlar: {{ .RunTime }}\r\n",
       "report": "🕰 Planlanmış Raporlar: {{ .RunTime }}\r\n",
       "datetime": "⏰ Tarih&Zaman: {{ .DateTime }}\r\n",
       "datetime": "⏰ Tarih&Zaman: {{ .DateTime }}\r\n",
-      "hostname": "💻 Sunucu: {{ .Hostname }}\r\n",
+      "hostname": "💻 Host: {{ .Hostname }}\r\n",
       "version": "🚀 3X-UI Sürümü: {{ .Version }}\r\n",
       "version": "🚀 3X-UI Sürümü: {{ .Version }}\r\n",
       "xrayVersion": "📡 Xray Sürümü: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Xray Sürümü: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
@@ -1017,7 +1434,7 @@
       "enabled": "🚨 Etkin: {{ .Enable }}\r\n",
       "enabled": "🚨 Etkin: {{ .Enable }}\r\n",
       "online": "🌐 Bağlantı durumu: {{ .Status }}\r\n",
       "online": "🌐 Bağlantı durumu: {{ .Status }}\r\n",
       "lastOnline": "🔙 Son çevrimiçi: {{ .Time }}\r\n",
       "lastOnline": "🔙 Son çevrimiçi: {{ .Time }}\r\n",
-      "email": "📧 E-posta: {{ .Email }}\r\n",
+      "email": "📧 Email: {{ .Email }}\r\n",
       "upload": "🔼 Yükleme: ↑{{ .Upload }}\r\n",
       "upload": "🔼 Yükleme: ↑{{ .Upload }}\r\n",
       "download": "🔽 İndirme: ↓{{ .Download }}\r\n",
       "download": "🔽 İndirme: ↓{{ .Download }}\r\n",
       "total": "📊 Toplam: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "total": "📊 Toplam: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
@@ -1087,11 +1504,11 @@
       "submitDisable": "Devre Dışı Olarak Gönder ☑️",
       "submitDisable": "Devre Dışı Olarak Gönder ☑️",
       "submitEnable": "Etkin Olarak Gönder ✅",
       "submitEnable": "Etkin Olarak Gönder ✅",
       "use_default": "🏷️ Varsayılanı Kullan",
       "use_default": "🏷️ Varsayılanı Kullan",
-      "change_id": "⚙️🔑 Kimlik",
+      "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 Şifre",
       "change_password": "⚙️🔑 Şifre",
-      "change_email": "⚙️📧 E-posta",
+      "change_email": "⚙️📧 Email",
       "change_comment": "⚙️💬 Yorum",
       "change_comment": "⚙️💬 Yorum",
-      "change_flow": "⚙️🚦 Akış",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "Tüm Trafikleri Sıfırla",
       "ResetAllTraffics": "Tüm Trafikleri Sıfırla",
       "SortedTrafficUsageReport": "Sıralı Trafik Kullanım Raporu"
       "SortedTrafficUsageReport": "Sıralı Trafik Kullanım Raporu"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Bir Gelen Seçin"
       "chooseInbound": "Bir Gelen Seçin"
     }
     }
   }
   }
-}
+}

+ 476 - 59
web/translation/uk-UA.json

@@ -8,15 +8,22 @@
   "save": "Зберегти",
   "save": "Зберегти",
   "logout": "Вийти",
   "logout": "Вийти",
   "create": "Створити",
   "create": "Створити",
+  "add": "Додати",
+  "remove": "Видалити",
   "update": "Оновити",
   "update": "Оновити",
   "copy": "Копіювати",
   "copy": "Копіювати",
   "copied": "Скопійовано",
   "copied": "Скопійовано",
+  "more": "більше",
   "download": "Завантажити",
   "download": "Завантажити",
   "remark": "Примітка",
   "remark": "Примітка",
   "enable": "Увімкнути",
   "enable": "Увімкнути",
   "protocol": "Протокол",
   "protocol": "Протокол",
   "search": "Пошук",
   "search": "Пошук",
   "filter": "Фільтр",
   "filter": "Фільтр",
+  "all": "Усі",
+  "from": "Від",
+  "to": "До",
+  "done": "Готово",
   "loading": "Завантаження...",
   "loading": "Завантаження...",
   "refresh": "Оновити",
   "refresh": "Оновити",
   "clear": "Очистити",
   "clear": "Очистити",
@@ -30,7 +37,7 @@
   "none": "Немає",
   "none": "Немає",
   "qrCode": "QR-Код",
   "qrCode": "QR-Код",
   "info": "Більше інформації",
   "info": "Більше інформації",
-  "edit": "Редагувати",
+  "edit": "Змінити",
   "delete": "Видалити",
   "delete": "Видалити",
   "reset": "Скидання",
   "reset": "Скидання",
   "noData": "Немає даних.",
   "noData": "Немає даних.",
@@ -41,14 +48,14 @@
   "transmission": "Протокол передачи",
   "transmission": "Протокол передачи",
   "host": "Хост",
   "host": "Хост",
   "path": "Шлях",
   "path": "Шлях",
-  "camouflage": "Маскування",
+  "camouflage": "Обфускація",
   "status": "Статус",
   "status": "Статус",
   "enabled": "Увімкнено",
   "enabled": "Увімкнено",
   "disabled": "Вимкнено",
   "disabled": "Вимкнено",
   "depleted": "Вичерпано",
   "depleted": "Вичерпано",
   "depletingSoon": "Вичерпується",
   "depletingSoon": "Вичерпується",
-  "offline": "Офлайн",
-  "online": "Онлайн",
+  "offline": "Не в мережі",
+  "online": "У мережі",
   "domainName": "Доменне ім`я",
   "domainName": "Доменне ім`я",
   "monitor": "Слухати IP",
   "monitor": "Слухати IP",
   "certificate": "Цифровий сертифікат",
   "certificate": "Цифровий сертифікат",
@@ -97,8 +104,9 @@
     "dashboard": "Огляд",
     "dashboard": "Огляд",
     "inbounds": "Вхідні",
     "inbounds": "Вхідні",
     "clients": "Клієнти",
     "clients": "Клієнти",
+    "groups": "Групи",
     "nodes": "Вузли",
     "nodes": "Вузли",
-    "settings": "Параметри панелі",
+    "settings": "Налаштування панелі",
     "xray": "Конфігурації Xray",
     "xray": "Конфігурації Xray",
     "apiDocs": "Документація API",
     "apiDocs": "Документація API",
     "logout": "Вийти",
     "logout": "Вийти",
@@ -120,16 +128,16 @@
     },
     },
     "index": {
     "index": {
       "title": "Огляд",
       "title": "Огляд",
-      "cpu": "ЦП",
+      "cpu": "CPU",
       "logicalProcessors": "Логічні процесори",
       "logicalProcessors": "Логічні процесори",
       "frequency": "Частота",
       "frequency": "Частота",
-      "swap": "Своп",
+      "swap": "Swap",
       "storage": "Сховище",
       "storage": "Сховище",
-      "memory": "ОЗП",
+      "memory": "RAM",
       "threads": "Потоки",
       "threads": "Потоки",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
-      "stopXray": "Зупинити",
-      "restartXray": "Перезапустити",
+      "stopXray": "Стоп",
+      "restartXray": "Перезапуск",
       "xraySwitch": "Версія",
       "xraySwitch": "Версія",
       "xrayUpdates": "Оновлення Xray",
       "xrayUpdates": "Оновлення Xray",
       "xraySwitchClick": "Виберіть версію, на яку ви хочете перейти.",
       "xraySwitchClick": "Виберіть версію, на яку ви хочете перейти.",
@@ -165,8 +173,8 @@
       "ipAddresses": "IP-адреси",
       "ipAddresses": "IP-адреси",
       "toggleIpVisibility": "Перемкнути видимість IP",
       "toggleIpVisibility": "Перемкнути видимість IP",
       "overallSpeed": "Загальна швидкість",
       "overallSpeed": "Загальна швидкість",
-      "upload": "Відправка",
-      "download": "Завантаження",
+      "upload": "Завантаження",
+      "download": "Завантажити",
       "totalData": "Загальний обсяг даних",
       "totalData": "Загальний обсяг даних",
       "sent": "Відправлено",
       "sent": "Відправлено",
       "received": "Отримано",
       "received": "Отримано",
@@ -226,7 +234,7 @@
       "customGeoErrUpdateAllIncomplete": "Не вдалося оновити один або кілька користувацьких джерел",
       "customGeoErrUpdateAllIncomplete": "Не вдалося оновити один або кілька користувацьких джерел",
       "customGeoEmpty": "Користувацьких джерел geo поки немає — натисніть «Додати», щоб створити",
       "customGeoEmpty": "Користувацьких джерел geo поки немає — натисніть «Додати», щоб створити",
       "dontRefresh": "Інсталяція триває, будь ласка, не оновлюйте цю сторінку",
       "dontRefresh": "Інсталяція триває, будь ласка, не оновлюйте цю сторінку",
-      "logs": "Журнали",
+      "logs": "Логи",
       "config": "Конфігурація",
       "config": "Конфігурація",
       "backup": "Резервна копія",
       "backup": "Резервна копія",
       "backupTitle": "Резервне копіювання та відновлення",
       "backupTitle": "Резервне копіювання та відновлення",
@@ -252,7 +260,7 @@
       "deployTo": "Розгорнути на",
       "deployTo": "Розгорнути на",
       "localPanel": "Локальна панель",
       "localPanel": "Локальна панель",
       "fallbacks": {
       "fallbacks": {
-        "title": "Фолбеки",
+        "title": "Fallback'и",
         "help": "Коли з'єднання на цьому інбаунді не збігається з жодним клієнтом, воно перенаправляється на інший інбаунд. Оберіть дочірній інбаунд нижче — поля маршрутизації (SNI / ALPN / Path / xver) заповняться автоматично з його транспорту; для більшості налаштувань більше нічого змінювати не треба. Кожен дочірній має слухати на 127.0.0.1 з security=none.",
         "help": "Коли з'єднання на цьому інбаунді не збігається з жодним клієнтом, воно перенаправляється на інший інбаунд. Оберіть дочірній інбаунд нижче — поля маршрутизації (SNI / ALPN / Path / xver) заповняться автоматично з його транспорту; для більшості налаштувань більше нічого змінювати не треба. Кожен дочірній має слухати на 127.0.0.1 з security=none.",
         "empty": "Фолбеків поки немає",
         "empty": "Фолбеків поки немає",
         "add": "Додати фолбек",
         "add": "Додати фолбек",
@@ -270,7 +278,7 @@
       },
       },
       "protocol": "Протокол",
       "protocol": "Протокол",
       "port": "Порт",
       "port": "Порт",
-      "portMap": "Порт-перехід",
+      "portMap": "Відображення портів",
       "traffic": "Трафік",
       "traffic": "Трафік",
       "details": "Деталі",
       "details": "Деталі",
       "transportConfig": "Транспорт",
       "transportConfig": "Транспорт",
@@ -292,11 +300,29 @@
       "delAllClients": "Видалити всіх клієнтів",
       "delAllClients": "Видалити всіх клієнтів",
       "delAllClientsConfirmTitle": "Видалити всіх {count} клієнтів із \"{remark}\"?",
       "delAllClientsConfirmTitle": "Видалити всіх {count} клієнтів із \"{remark}\"?",
       "delAllClientsConfirmContent": "Видаляє всіх клієнтів цього вхідного й скидає їхні записи трафіку. Сам вхідний зберігається. Цю дію не можна скасувати.",
       "delAllClientsConfirmContent": "Видаляє всіх клієнтів цього вхідного й скидає їхні записи трафіку. Сам вхідний зберігається. Цю дію не можна скасувати.",
+      "attachClients": "Прив'язати клієнтів до…",
+      "addClientsToGroup": "Додати клієнтів до групи…",
+      "attachClientsTitle": "Прив'язати клієнтів з «{remark}»",
+      "attachClientsDesc": "Прив'язує тих самих {count} клієнт(ів) (з тим самим UUID/паролем і спільним трафіком) до обраних вхідних. Вони залишаються і на цьому вхідному.",
+      "attachClientsTargets": "Цільові вхідні",
+      "attachClientsNoTargets": "Немає інших сумісних вхідних для прив'язки.",
+      "attachClientsResult": "Прив'язано {attached}, пропущено {skipped}.",
+      "attachClientsResultMixed": "Прив'язано {attached}, пропущено {skipped}, помилок {errors}.",
+      "attachClientsSelectLabel": "Клієнти для прив'язки",
+      "attachClientsSearchPlaceholder": "Пошук email або коментаря",
+      "attachClientsStatusDisabled": "Вимкнено",
+      "attachClientsSelectedCount": "Обрано {selected} з {total}",
+      "detachClients": "Від'єднати клієнтів",
+      "detachClientsTitle": "Від'єднати клієнтів з «{remark}»",
+      "detachClientsDesc": "Видаляє обраних клієнт(ів) лише з цього вхідного. Записи клієнтів зберігаються (використовуйте Delete для повного видалення). У джерела всього {count} клієнт(ів).",
+      "detachClientsResult": "Від'єднано {detached}, пропущено {skipped}.",
+      "detachClientsResultMixed": "Від'єднано {detached}, пропущено {skipped}, помилок {errors}.",
+      "detachClientsSelectLabel": "Клієнти для від'єднання",
       "exportLinksTitle": "Експортувати посилання вхідних",
       "exportLinksTitle": "Експортувати посилання вхідних",
       "exportSubsTitle": "Експортувати посилання підписок",
       "exportSubsTitle": "Експортувати посилання підписок",
       "exportAllLinksTitle": "Експортувати всі посилання вхідних",
       "exportAllLinksTitle": "Експортувати всі посилання вхідних",
       "exportAllSubsTitle": "Експортувати всі посилання підписок",
       "exportAllSubsTitle": "Експортувати всі посилання підписок",
-      "inboundJsonTitle": "JSON вхідних",
+      "inboundJsonTitle": "JSON вхідного",
       "deleteClient": "Видалити клієнта",
       "deleteClient": "Видалити клієнта",
       "deleteClientContent": "Ви впевнені, що хочете видалити клієнт?",
       "deleteClientContent": "Ви впевнені, що хочете видалити клієнт?",
       "resetTrafficContent": "Ви впевнені, що хочете скинути трафік?",
       "resetTrafficContent": "Ви впевнені, що хочете скинути трафік?",
@@ -306,7 +332,7 @@
       "destinationPort": "Порт призначення",
       "destinationPort": "Порт призначення",
       "targetAddress": "Цільова адреса",
       "targetAddress": "Цільова адреса",
       "monitorDesc": "Залиште порожнім, щоб слухати всі IP-адреси",
       "monitorDesc": "Залиште порожнім, щоб слухати всі IP-адреси",
-      "meansNoLimit": "= Необмежено. (одиниця: ГБ)",
+      "meansNoLimit": "= Без обмежень. (одиниця: ГБ)",
       "totalFlow": "Загальна витрата",
       "totalFlow": "Загальна витрата",
       "leaveBlankToNeverExpire": "Залиште порожнім, щоб ніколи не закінчувався",
       "leaveBlankToNeverExpire": "Залиште порожнім, щоб ніколи не закінчувався",
       "noRecommendKeepDefault": "Рекомендується зберегти значення за замовчуванням",
       "noRecommendKeepDefault": "Рекомендується зберегти значення за замовчуванням",
@@ -333,7 +359,7 @@
       "delDepletedClients": "Видалити вичерпані клієнти",
       "delDepletedClients": "Видалити вичерпані клієнти",
       "delDepletedClientsTitle": "Видалити вичерпані клієнти",
       "delDepletedClientsTitle": "Видалити вичерпані клієнти",
       "delDepletedClientsContent": "Ви впевнені, що хочете видалити всі вичерпані клієнти?",
       "delDepletedClientsContent": "Ви впевнені, що хочете видалити всі вичерпані клієнти?",
-      "email": "Електронна пошта",
+      "email": "Email",
       "emailDesc": "Будь ласка, надайте унікальну адресу електронної пошти.",
       "emailDesc": "Будь ласка, надайте унікальну адресу електронної пошти.",
       "IPLimit": "Обмеження IP",
       "IPLimit": "Обмеження IP",
       "IPLimitDesc": "Вимикає вхідний, якщо кількість перевищує встановлене значення. (0 = вимкнено)",
       "IPLimitDesc": "Вимикає вхідний, якщо кількість перевищує встановлене значення. (0 = вимкнено)",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "Журнал історії IP-адрес. (щоб увімкнути вхідну після вимкнення, очистіть журнал)",
       "IPLimitlogDesc": "Журнал історії IP-адрес. (щоб увімкнути вхідну після вимкнення, очистіть журнал)",
       "IPLimitlogclear": "Очистити журнал",
       "IPLimitlogclear": "Очистити журнал",
       "setDefaultCert": "Установити сертифікат з панелі",
       "setDefaultCert": "Установити сертифікат з панелі",
-      "streamTab": "Потік",
+      "setDefaultCertEmpty": "Для панелі не налаштовано сертифікат. Спочатку встановіть його в Налаштуваннях.",
+      "streamTab": "Stream",
       "securityTab": "Безпека",
       "securityTab": "Безпека",
-      "sniffingTab": "Сніфінг",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "Лише метадані",
       "sniffingMetadataOnly": "Лише метадані",
       "sniffingRouteOnly": "Лише маршрутизація",
       "sniffingRouteOnly": "Лише маршрутизація",
       "sniffingIpsExcluded": "Виключені IP",
       "sniffingIpsExcluded": "Виключені IP",
@@ -361,15 +388,14 @@
         "allHelp": "Повний об'єкт вхідного з усіма полями в одному редакторі.",
         "allHelp": "Повний об'єкт вхідного з усіма полями в одному редакторі.",
         "settings": "Налаштування",
         "settings": "Налаштування",
         "settingsHelp": "Обгортка блоку settings Xray:",
         "settingsHelp": "Обгортка блоку settings Xray:",
-        "sniffing": "Сніфінг",
+        "sniffing": "Sniffing",
         "sniffingHelp": "Обгортка блоку sniffing Xray:",
         "sniffingHelp": "Обгортка блоку sniffing Xray:",
-        "stream": "Потік",
+        "stream": "Stream",
         "streamHelp": "Обгортка блоку stream Xray:",
         "streamHelp": "Обгортка блоку stream Xray:",
         "jsonErrorPrefix": "Розширений JSON"
         "jsonErrorPrefix": "Розширений JSON"
       },
       },
       "telegramDesc": "Будь ласка, вкажіть ID чату Telegram. (використовуйте команду '/id' у боті) або ({'@'}userinfobot)",
       "telegramDesc": "Будь ласка, вкажіть ID чату Telegram. (використовуйте команду '/id' у боті) або ({'@'}userinfobot)",
       "subscriptionDesc": "Щоб знайти URL-адресу вашої підписки, перейдіть до «Деталі». Крім того, ви можете використовувати одне ім'я для кількох клієнтів.",
       "subscriptionDesc": "Щоб знайти URL-адресу вашої підписки, перейдіть до «Деталі». Крім того, ви можете використовувати одне ім'я для кількох клієнтів.",
-      "info": "Інформація",
       "same": "Те саме",
       "same": "Те саме",
       "inboundData": "Вхідні дані",
       "inboundData": "Вхідні дані",
       "exportInbound": "Експортувати вхідні",
       "exportInbound": "Експортувати вхідні",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Помилка при отриманні сертифіката mldsa65.",
         "getNewmldsa65Error": "Помилка при отриманні сертифіката mldsa65.",
         "getNewVlessEncError": "Помилка при отриманні сертифіката VlessEnc."
         "getNewVlessEncError": "Помилка при отриманні сертифіката VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Вгору",
+        "moveDown": "Вниз",
+        "addAll": "Додати всі",
+        "addAllFallbackTooltip": "Додає рядок fallback для кожного придатного вхідного, ще не приєднаного",
+        "peers": "Peers",
+        "addPeer": "Додати peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Лише для Windows. CIDR'и автоматично додаються до системної таблиці маршрутизації, щоб відповідний трафік проходив через TUN.",
+        "autoOutboundsInterface": "Авто-інтерфейс вихідних",
+        "autoOutboundsInterfaceTooltip": "Фізичний інтерфейс для вихідного трафіку. Використовуйте 'auto' для виявлення; вмикається автоматично, коли налаштовано Auto system routes.",
+        "rewriteAddress": "Переписати адресу",
+        "rewritePort": "Переписати порт",
+        "allowedNetwork": "Дозволена мережа",
+        "followRedirect": "Слідувати redirect",
+        "accounts": "Акаунти",
+        "allowTransparent": "Дозволити прозорий",
+        "encryptionMethod": "Метод шифрування",
+        "visionTestseed": "Vision testseed",
+        "version": "Версія",
+        "udpIdleTimeout": "UDP idle timeout (с)",
+        "masquerade": "Masquerade",
+        "type": "Тип",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Переписати Host",
+        "skipTlsVerify": "Пропустити TLS verify",
+        "directory": "Каталог",
+        "statusCode": "Код статусу",
+        "body": "Body",
+        "headers": "Заголовки",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Версія запиту",
+        "requestMethod": "Метод запиту",
+        "requestPath": "Шлях запиту",
+        "requestHeaders": "Заголовки запиту",
+        "responseVersion": "Версія відповіді",
+        "responseStatus": "Статус відповіді",
+        "responseReason": "Причина відповіді",
+        "responseHeaders": "Заголовки відповіді",
+        "heartbeatPeriod": "Період heartbeat",
+        "serviceName": "Назва сервісу",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Макс. буферизоване завантаження",
+        "maxUploadSize": "Макс. розмір завантаження (байт)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Server Max Header Bytes",
+        "paddingBytes": "Padding Bytes",
+        "uplinkHttpMethod": "HTTP-метод Uplink",
+        "paddingObfsMode": "Padding Obfs Mode",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding Placement",
+        "paddingMethod": "Padding Method",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Без заголовка SSE",
+        "ttiMs": "TTI (мс)",
+        "uplinkMbps": "Uplink (МБ/с)",
+        "downlinkMbps": "Downlink (МБ/с)",
+        "cwndMultiplier": "Множник CWND",
+        "maxSendingWindow": "Макс. вікно відправки",
+        "externalProxy": "External Proxy",
+        "sniPlaceholder": "SNI (за замовчуванням = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "За замовчуванням",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Лише V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "Довірений X-Forwarded-For",
+        "addressPortStrategy": "Стратегія адрес+порт",
+        "tryDelayMs": "Затримка спроби (мс)",
+        "prioritizeIPv6": "Пріоритет IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Макс. одночасних спроб",
+        "customSockopt": "Користувацький sockopt",
+        "addCustomOption": "Додати опцію",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Авто",
+        "minMaxVersion": "Мін/Макс версія",
+        "rejectUnknownSni": "Відхиляти невідомий SNI",
+        "disableSystemRoot": "Вимкнути System Root",
+        "sessionResumption": "Відновлення сесії",
+        "oneTimeLoading": "Одноразове завантаження",
+        "usageOption": "Опція використання",
+        "buildChain": "Build Chain",
+        "echKey": "ECH key",
+        "echConfig": "ECH config",
+        "getNewEchCert": "Отримати новий ECH-сертифікат",
+        "show": "Показати",
+        "xver": "Xver",
+        "target": "Ціль",
+        "maxTimeDiff": "Макс. різниця в часі (мс)",
+        "minClientVer": "Мін. версія клієнта",
+        "maxClientVer": "Макс. версія клієнта",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Отримати новий сертифікат",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Отримати новий Seed"
+      },
+      "info": {
+        "mode": "Режим",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Назва інтерфейсу",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Інтерфейс вихідних",
+        "autoSystemRoutes": "Авто-маршрути системи",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN без kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Конфіг Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Запит",
           "request": "Запит",
@@ -456,6 +615,20 @@
       "days": "Дні",
       "days": "Дні",
       "renew": "Авто-продовження",
       "renew": "Авто-продовження",
       "renewDesc": "Автоматичне продовження після закінчення. (0 = вимкнено) (одиниця: день)",
       "renewDesc": "Автоматичне продовження після закінчення. (0 = вимкнено) (одиниця: день)",
+      "searchPlaceholder": "Пошук email, коментаря, sub ID, UUID, паролю, auth…",
+      "filterTitle": "Фільтр клієнтів",
+      "clearAllFilters": "Очистити все",
+      "sortOldest": "Спочатку старі",
+      "sortNewest": "Спочатку нові",
+      "sortRecentlyUpdated": "Нещодавно оновлені",
+      "sortRecentlyOnline": "Нещодавно у мережі",
+      "sortEmailAZ": "Email А→Я",
+      "sortEmailZA": "Email Я→А",
+      "sortMostTraffic": "Більше трафіку",
+      "sortHighestRemaining": "Більше залишку",
+      "sortExpiringSoonest": "Швидше закінчуються",
+      "has": "Має",
+      "hasNot": "Не має",
       "title": "Клієнти",
       "title": "Клієнти",
       "actions": "Дії",
       "actions": "Дії",
       "totalGB": "Усього надіслано/отримано (ГБ)",
       "totalGB": "Усього надіслано/отримано (ГБ)",
@@ -466,6 +639,9 @@
       "subId": "ID підписки",
       "subId": "ID підписки",
       "online": "У мережі",
       "online": "У мережі",
       "email": "Email",
       "email": "Email",
+      "group": "Група",
+      "groupDesc": "Логічна мітка для групування пов'язаних клієнтів (напр. команда, клієнт, регіон). Фільтрується з панелі інструментів.",
+      "groupPlaceholder": "напр. customer-a",
       "comment": "Коментар",
       "comment": "Коментар",
       "traffic": "Трафік",
       "traffic": "Трафік",
       "offline": "Не в мережі",
       "offline": "Не в мережі",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Скинути трафік усіх клієнтів",
       "resetAllTraffics": "Скинути трафік усіх клієнтів",
       "resetAllTrafficsTitle": "Скинути трафік усіх клієнтів?",
       "resetAllTrafficsTitle": "Скинути трафік усіх клієнтів?",
       "resetAllTrafficsContent": "Лічильники відправлення/отримання кожного клієнта обнулюються. Квоти й термін дії не змінюються. Цю дію неможливо скасувати.",
       "resetAllTrafficsContent": "Лічильники відправлення/отримання кожного клієнта обнулюються. Квоти й термін дії не змінюються. Цю дію неможливо скасувати.",
-      "empty": "Клієнтів ще немає — додайте першого, щоб почати.",
       "deleteConfirmTitle": "Видалити клієнта {email}?",
       "deleteConfirmTitle": "Видалити клієнта {email}?",
       "deleteConfirmContent": "Клієнт буде вилучений з усіх прив'язаних вхідних, його запис трафіку буде знищено. Цю дію неможливо скасувати.",
       "deleteConfirmContent": "Клієнт буде вилучений з усіх прив'язаних вхідних, його запис трафіку буде знищено. Цю дію неможливо скасувати.",
       "deleteSelected": "Видалити ({count})",
       "deleteSelected": "Видалити ({count})",
       "adjustSelected": "Змінити ({count})",
       "adjustSelected": "Змінити ({count})",
+      "subLinksSelected": "Sub-посилання ({count})",
+      "addToGroupTitle": "Додати {count} клієнт(ів) до групи",
+      "addToGroupTooltip": "Виберіть існуючу групу або введіть нову назву. Використовуйте Ungroup, щоб вилучити клієнтів із поточної групи.",
+      "addToGroupPlaceholder": "Назва групи",
+      "addToGroupSuccessToast": "{count} клієнт(ів) додано до {group}",
+      "ungroupSuccessToast": "Групу очищено у {count} клієнт(ів)",
+      "ungroup": "Розгрупувати",
+      "ungroupConfirmTitle": "Видалити {count} клієнт(ів) з їхньої групи?",
+      "ungroupConfirmContent": "Очищує мітку групи у кожного обраного клієнта. Самі клієнти зберігаються (використовуйте Delete для повного видалення).",
+      "addToGroup": "Додати до групи",
+      "attach": "Прив'язати",
+      "adjust": "Коригування",
+      "subLinks": "Sub-посилання",
+      "selectedCount": "Обрано {count}",
+      "attachSelected": "Прив'язати ({count})",
+      "attachToInboundsTitle": "Прив'язати {count} клієнт(ів) до вхідних",
+      "attachToInboundsDesc": "Прив'язує обрані {count} клієнт(ів) (той самий UUID/пароль і спільний трафік) до обраних вхідних. Існуючі прив'язки зберігаються.",
+      "attachToInboundsTargets": "Цільові вхідні",
+      "attachToInboundsNoTargets": "Немає доступних багатокористувацьких вхідних для прив'язки.",
+      "detachSelected": "Від'єднати ({count})",
+      "detach": "Від'єднати",
+      "detachFromInboundsTitle": "Від'єднати {count} клієнт(ів) від вхідних",
+      "detachFromInboundsDesc": "Видаляє обраних {count} клієнт(ів) з обраних вхідних. Пари, де клієнт не був прив'язаний, тихо пропускаються. Записи клієнтів зберігаються (використовуйте Delete для повного видалення).",
+      "detachFromInboundsTargets": "Вхідні для від'єднання",
+      "detachFromInboundsNoTargets": "Немає доступних багатокористувацьких вхідних.",
+      "detachFromInboundsResult": "Від'єднано {detached}, пропущено {skipped}.",
+      "detachFromInboundsResultMixed": "Від'єднано {detached}, пропущено {skipped}, помилок {errors}.",
+      "subLinksTitle": "Sub-посилання ({count})",
+      "subLinkColumn": "URL підписки",
+      "subJsonLinkColumn": "URL JSON-підписки",
+      "subLinksCopyAll": "Копіювати все",
+      "subLinksCopiedAll": "Скопійовано {count} посилань",
+      "subLinksEmpty": "Жоден з обраних клієнтів не має ID підписки.",
+      "subLinksDisabled": "Сервіс підписки вимкнено.",
+      "subLinksDisabledHint": "Увімкніть підписку в Налаштування панелі → Підписка для генерації посилань.",
       "bulkDeleteConfirmTitle": "Видалити {count} клієнтів?",
       "bulkDeleteConfirmTitle": "Видалити {count} клієнтів?",
       "bulkDeleteConfirmContent": "Кожен вибраний клієнт вилучається з усіх прив'язаних вхідних, його запис трафіку знищується. Цю дію неможливо скасувати.",
       "bulkDeleteConfirmContent": "Кожен вибраний клієнт вилучається з усіх прив'язаних вхідних, його запис трафіку знищується. Цю дію неможливо скасувати.",
       "bulkAdjustTitle": "Змінити {count} клієнтів",
       "bulkAdjustTitle": "Змінити {count} клієнтів",
@@ -504,11 +714,12 @@
       "delDepleted": "Видалити вичерпаних",
       "delDepleted": "Видалити вичерпаних",
       "delDepletedConfirmTitle": "Видалити вичерпаних клієнтів?",
       "delDepletedConfirmTitle": "Видалити вичерпаних клієнтів?",
       "delDepletedConfirmContent": "Видаляються всі клієнти, у яких вичерпана квота трафіку або сплив термін. Цю дію неможливо скасувати.",
       "delDepletedConfirmContent": "Видаляються всі клієнти, у яких вичерпана квота трафіку або сплив термін. Цю дію неможливо скасувати.",
-      "auth": "Auth",
-      "hysteriaAuth": "Auth для Hysteria",
+      "auth": "Авторизація",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "Безпека VMess",
+      "reverseTag": "Зворотний тег",
       "reverseTagPlaceholder": "Необов'язковий Reverse tag",
       "reverseTagPlaceholder": "Необов'язковий Reverse tag",
       "telegramId": "ID користувача Telegram",
       "telegramId": "ID користувача Telegram",
       "telegramIdPlaceholder": "Числовий ID користувача Telegram (0 = немає)",
       "telegramIdPlaceholder": "Числовий ID користувача Telegram (0 = немає)",
@@ -528,13 +739,51 @@
         "delDepleted": "Видалено вичерпаних клієнтів: {count}"
         "delDepleted": "Видалено вичерпаних клієнтів: {count}"
       }
       }
     },
     },
+    "groups": {
+      "title": "Групи",
+      "name": "Назва",
+      "clientCount": "Клієнтів у групі",
+      "totalGroups": "Всього груп",
+      "totalGroupedClients": "Клієнти з групою",
+      "emptyGroups": "Порожні групи",
+      "addGroup": "Додати групу",
+      "createSuccess": "Групу «{name}» створено.",
+      "rename": "Перейменувати",
+      "renameTitle": "Перейменувати {name}",
+      "renameCollision": "Група з назвою «{name}» вже існує.",
+      "renameSuccess": "Групу перейменовано на {count} клієнт(ах).",
+      "deleteConfirmTitle": "Видалити групу {name}?",
+      "deleteConfirmContent": "Це видаляє групу й очищує її мітку у {count} клієнт(ів). Самі клієнти не видаляються.",
+      "deleteSuccess": "Групу очищено у {count} клієнт(ів).",
+      "resetTraffic": "Скинути трафік",
+      "resetConfirmTitle": "Скинути трафік групи {name}?",
+      "resetConfirmContent": "Це обнулить up/down для всіх {count} клієнт(ів) у цій групі.",
+      "resetSuccess": "Скинуто трафік у {count} клієнт(ів).",
+      "adjustSuccess": "Скориговано {count} клієнт(ів) у {name}.",
+      "emptyForAction": "У цій групі ще немає клієнтів.",
+      "deleteGroupOnly": "Видалити групу (зберегти клієнтів)",
+      "deleteClients": "Видалити клієнтів групи",
+      "deleteClientsConfirmTitle": "Видалити всіх клієнтів у {name}?",
+      "deleteClientsConfirmContent": "Це безповоротно видалить {count} клієнт(ів) разом з їхніми записами трафіку. Мітка групи також очищується. Дію не можна скасувати.",
+      "deleteClientsSuccess": "Видалено {count} клієнт(ів).",
+      "deleteClientsMixed": "{ok} видалено, {failed} пропущено",
+      "addToGroup": "Додати клієнтів…",
+      "addToGroupTitle": "Додати клієнтів до групи «{name}»",
+      "addToGroupDesc": "Виберіть клієнтів для додавання в цю групу. Існуючі прив'язки до вхідних зберігаються; змінюється лише мітка групи. Клієнти, які вже в цій групі, не відображаються.",
+      "addToGroupEmpty": "Немає інших клієнтів для додавання.",
+      "addToGroupResult": "Додано {count} клієнт(ів) до {name}.",
+      "removeFromGroup": "Видалити клієнтів…",
+      "removeFromGroupTitle": "Видалити клієнтів з групи «{name}»",
+      "removeFromGroupDesc": "Виберіть учасників для видалення з цієї групи. Самі клієнти зберігаються (використовуйте «Видалити клієнтів групи» для повного видалення).",
+      "removeFromGroupResult": "Видалено {count} клієнт(ів) з {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Вузли",
       "title": "Вузли",
       "addNode": "Додати вузол",
       "addNode": "Додати вузол",
-      "editNode": "Редагувати вузол",
+      "editNode": "Змінити вузол",
       "totalNodes": "Усього вузлів",
       "totalNodes": "Усього вузлів",
-      "onlineNodes": "Онлайн",
-      "offlineNodes": "Офлайн",
+      "onlineNodes": "У мережі",
+      "offlineNodes": "Не в мережі",
       "avgLatency": "Середня затримка",
       "avgLatency": "Середня затримка",
       "name": "Назва",
       "name": "Назва",
       "namePlaceholder": "напр. de-frankfurt-1",
       "namePlaceholder": "напр. de-frankfurt-1",
@@ -544,7 +793,7 @@
       "address": "Адреса",
       "address": "Адреса",
       "port": "Порт",
       "port": "Порт",
       "basePath": "Базовий шлях",
       "basePath": "Базовий шлях",
-      "apiToken": "Токен API",
+      "apiToken": "API Token",
       "apiTokenPlaceholder": "Токен зі сторінки Налаштувань віддаленої панелі",
       "apiTokenPlaceholder": "Токен зі сторінки Налаштувань віддаленої панелі",
       "apiTokenHint": "Віддалена панель показує свій токен API в Налаштуваннях → Токен API.",
       "apiTokenHint": "Віддалена панель показує свій токен API в Налаштуваннях → Токен API.",
       "regenerate": "Перегенерувати токен",
       "regenerate": "Перегенерувати токен",
@@ -570,8 +819,8 @@
       "deleteConfirmTitle": "Видалити вузол \"{name}\"?",
       "deleteConfirmTitle": "Видалити вузол \"{name}\"?",
       "deleteConfirmContent": "Це зупинить моніторинг вузла. Сама віддалена панель не зазнає змін.",
       "deleteConfirmContent": "Це зупинить моніторинг вузла. Сама віддалена панель не зазнає змін.",
       "statusValues": {
       "statusValues": {
-        "online": "Онлайн",
-        "offline": "Офлайн",
+        "online": "У мережі",
+        "offline": "Не в мережі",
         "unknown": "Невідомо"
         "unknown": "Невідомо"
       },
       },
       "toasts": {
       "toasts": {
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "Базовий шлях за замовчуванням \"/\" широко відомий — змініть його на випадковий.",
       "warnDefaultBasePath": "Базовий шлях за замовчуванням \"/\" широко відомий — змініть його на випадковий.",
       "warnDefaultSubPath": "Шлях підписки за замовчуванням \"/sub/\" широко відомий — змініть його.",
       "warnDefaultSubPath": "Шлях підписки за замовчуванням \"/sub/\" широко відомий — змініть його.",
       "warnDefaultJsonPath": "JSON-шлях підписки за замовчуванням \"/json/\" широко відомий — змініть його.",
       "warnDefaultJsonPath": "JSON-шлях підписки за замовчуванням \"/json/\" широко відомий — змініть його.",
-      "TGBotSettings": "Telegram Бот",
+      "TGBotSettings": "Telegramот",
       "panelListeningIP": "Слухати IP",
       "panelListeningIP": "Слухати IP",
       "panelListeningIPDesc": "IP-адреса для веб-панелі. (залиште порожнім, щоб слухати всі IP-адреси)",
       "panelListeningIPDesc": "IP-адреса для веб-панелі. (залиште порожнім, щоб слухати всі IP-адреси)",
       "panelListeningDomain": "Домен прослуховування",
       "panelListeningDomain": "Домен прослуховування",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Шлях до файлу відкритого ключа для веб-панелі. (починається з ‘/‘)",
       "publicKeyPathDesc": "Шлях до файлу відкритого ключа для веб-панелі. (починається з ‘/‘)",
       "privateKeyPath": "Шлях приватного ключа",
       "privateKeyPath": "Шлях приватного ключа",
       "privateKeyPathDesc": "Шлях до файлу приватного ключа для веб-панелі. (починається з ‘/‘)",
       "privateKeyPathDesc": "Шлях до файлу приватного ключа для веб-панелі. (починається з ‘/‘)",
-      "panelUrlPath": "Шлях URL",
+      "panelUrlPath": "URI-шлях",
       "panelUrlPathDesc": "Шлях URL для веб-панелі. (починається з ‘/‘ і закінчується ‘/‘)",
       "panelUrlPathDesc": "Шлях URL для веб-панелі. (починається з ‘/‘ і закінчується ‘/‘)",
       "pageSize": "Розмір сторінки",
       "pageSize": "Розмір сторінки",
       "pageSizeDesc": "Визначити розмір сторінки для вхідної таблиці. (0 = вимкнено)",
       "pageSizeDesc": "Визначити розмір сторінки для вхідної таблиці. (0 = вимкнено)",
+      "panelProxy": "Мережевий проксі панелі",
+      "panelProxyDesc": "Маршрутизує власні вихідні запити панелі (оновлення geo, перевірки версій Xray/панелі, Telegram) через цей проксі для обходу фільтрації GitHub/Telegram на стороні сервера. Приймає socks5:// або http(s)://, напр. локальний SOCKS-вхідний Xray. Залиште порожнім для прямого підключення.",
       "remarkModel": "Модель зауваження та роздільний символ",
       "remarkModel": "Модель зауваження та роздільний символ",
       "datepicker": "Тип календаря",
       "datepicker": "Тип календаря",
       "datepickerPlaceholder": "Виберіть дату",
       "datepickerPlaceholder": "Виберіть дату",
@@ -630,11 +881,11 @@
       "newPassword": "Новий пароль",
       "newPassword": "Новий пароль",
       "telegramBotEnable": "Увімкнути Telegram Bot",
       "telegramBotEnable": "Увімкнути Telegram Bot",
       "telegramBotEnableDesc": "Вмикає бота Telegram.",
       "telegramBotEnableDesc": "Вмикає бота Telegram.",
-      "telegramToken": "Telegram Токен",
+      "telegramToken": "Telegramокен",
       "telegramTokenDesc": "Токен бота Telegram, отриманий від '{'@'}BotFather'.",
       "telegramTokenDesc": "Токен бота Telegram, отриманий від '{'@'}BotFather'.",
-      "telegramProxy": "SOCKS Проксі",
+      "telegramProxy": "SOCKS-проксі",
       "telegramProxyDesc": "Вмикає проксі-сервер SOCKS5 для підключення до Telegram. (відкоригуйте параметри відповідно до посібника)",
       "telegramProxyDesc": "Вмикає проксі-сервер SOCKS5 для підключення до Telegram. (відкоригуйте параметри відповідно до посібника)",
-      "telegramAPIServer": "Сервер Telegram API",
+      "telegramAPIServer": "Telegram API сервер",
       "telegramAPIServerDesc": "Сервер Telegram API для використання. Залиште поле порожнім, щоб використовувати сервер за умовчанням.",
       "telegramAPIServerDesc": "Сервер Telegram API для використання. Залиште поле порожнім, щоб використовувати сервер за умовчанням.",
       "telegramChatId": "Ідентифікатор чату адміністратора",
       "telegramChatId": "Ідентифікатор чату адміністратора",
       "telegramChatIdDesc": "Ідентифікатори чату адміністратора Telegram. (розділені комами) (отримайте тут {'@'}userinfobot) або (використовуйте команду '/id' у боті)",
       "telegramChatIdDesc": "Ідентифікатори чату адміністратора Telegram. (розділені комами) (отримайте тут {'@'}userinfobot) або (використовуйте команду '/id' у боті)",
@@ -658,6 +909,8 @@
       "subEnable": "Увімкнути службу підписки",
       "subEnable": "Увімкнути службу підписки",
       "subEnableDesc": "Вмикає службу підписки.",
       "subEnableDesc": "Вмикає службу підписки.",
       "subJsonEnable": "Увімкнути/вимкнути JSON-кінець підписки незалежно.",
       "subJsonEnable": "Увімкнути/вимкнути JSON-кінець підписки незалежно.",
+      "subJsonEnableTitle": "JSON-підписка",
+      "subClashEnableTitle": "Підписка Clash / Mihomo",
       "subTitle": "Назва Підписки",
       "subTitle": "Назва Підписки",
       "subTitleDesc": "Назва, яка відображається у VPN-клієнті",
       "subTitleDesc": "Назва, яка відображається у VPN-клієнті",
       "subSupportUrl": "URL підтримки",
       "subSupportUrl": "URL підтримки",
@@ -678,13 +931,13 @@
       "subCertPathDesc": "Шлях до файлу відкритого ключа для служби підписки. (починається з ‘/‘)",
       "subCertPathDesc": "Шлях до файлу відкритого ключа для служби підписки. (починається з ‘/‘)",
       "subKeyPath": "Шлях приватного ключа",
       "subKeyPath": "Шлях приватного ключа",
       "subKeyPathDesc": "Шлях до файлу приватного ключа для служби підписки. (починається з ‘/‘)",
       "subKeyPathDesc": "Шлях до файлу приватного ключа для служби підписки. (починається з ‘/‘)",
-      "subPath": "Шлях URI",
+      "subPath": "URI-шлях",
       "subPathDesc": "Шлях URI для служби підписки. (починається з ‘/‘ і закінчується ‘/‘)",
       "subPathDesc": "Шлях URI для служби підписки. (починається з ‘/‘ і закінчується ‘/‘)",
       "subDomain": "Домен прослуховування",
       "subDomain": "Домен прослуховування",
       "subDomainDesc": "Ім'я домену для служби підписки. (залиште порожнім, щоб слухати всі домени та IP-адреси)",
       "subDomainDesc": "Ім'я домену для служби підписки. (залиште порожнім, щоб слухати всі домени та IP-адреси)",
       "subUpdates": "Інтервали оновлення",
       "subUpdates": "Інтервали оновлення",
       "subUpdatesDesc": "Інтервали оновлення URL-адреси підписки в клієнтських програмах. (одиниця: година)",
       "subUpdatesDesc": "Інтервали оновлення URL-адреси підписки в клієнтських програмах. (одиниця: година)",
-      "subEncrypt": "Закодувати",
+      "subEncrypt": "Кодувати",
       "subEncryptDesc": "Повернений вміст послуги підписки матиме кодування Base64.",
       "subEncryptDesc": "Повернений вміст послуги підписки матиме кодування Base64.",
       "subShowInfo": "Показати інформацію про використання",
       "subShowInfo": "Показати інформацію про використання",
       "subShowInfoDesc": "Залишок трафіку та дата відображатимуться в клієнтських програмах.",
       "subShowInfoDesc": "Залишок трафіку та дата відображатимуться в клієнтських програмах.",
@@ -693,7 +946,7 @@
       "subURI": "URI зворотного проксі",
       "subURI": "URI зворотного проксі",
       "subURIDesc": "URI до URL-адреси підписки для використання за проксі.",
       "subURIDesc": "URI до URL-адреси підписки для використання за проксі.",
       "externalTrafficInformEnable": "Інформація про зовнішній трафік",
       "externalTrafficInformEnable": "Інформація про зовнішній трафік",
-      "externalTrafficInformEnableDesc": "Інформувати зовнішній API про кожне оновлення трафіку.",
+      "externalTrafficInformEnableDesc": "Повідомляти зовнішній API про кожне оновлення трафіку.",
       "externalTrafficInformURI": "Інформаційний URI зовнішнього трафіку",
       "externalTrafficInformURI": "Інформаційний URI зовнішнього трафіку",
       "externalTrafficInformURIDesc": "Оновлення трафіку надсилаються на цей URI.",
       "externalTrafficInformURIDesc": "Оновлення трафіку надсилаються на цей URI.",
       "restartXrayOnClientDisable": "Перезапускати Xray після авто-вимкнення",
       "restartXrayOnClientDisable": "Перезапускати Xray після авто-вимкнення",
@@ -703,6 +956,54 @@
       "fragmentSett": "Параметри фрагментації",
       "fragmentSett": "Параметри фрагментації",
       "noisesDesc": "Увімкнути Noises.",
       "noisesDesc": "Увімкнути Noises.",
       "noisesSett": "Налаштування Noises",
       "noisesSett": "Налаштування Noises",
+      "trustedProxyCidrs": "Довірені CIDR проксі",
+      "trustedProxyCidrsDesc": "IP/CIDR через кому, яким дозволено встановлювати заголовки forwarded host, proto та client IP.",
+      "ldap": {
+        "enable": "Увімкнути LDAP-синхронізацію",
+        "host": "LDAP-хост",
+        "port": "Порт LDAP",
+        "useTls": "Використовувати TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Налаштовано; залиште порожнім для збереження поточного паролю.",
+        "passwordUnconfigured": "Не налаштовано.",
+        "passwordPlaceholder": "Налаштовано — введіть нове значення для заміни",
+        "baseDn": "Base DN",
+        "userFilter": "Фільтр користувача",
+        "userAttr": "Атрибут користувача (username/email)",
+        "vlessField": "Атрибут VLESS-flag",
+        "flagField": "Загальний атрибут flag (опц.)",
+        "flagFieldDesc": "Якщо задано, перевизначає VLESS flag — напр. shadowInactive.",
+        "truthyValues": "Truthy-значення",
+        "truthyValuesDesc": "Через кому; за замовч.: true,1,yes,on",
+        "invertFlag": "Інвертувати flag",
+        "invertFlagDesc": "Увімкніть, коли атрибут означає «вимкнено» (напр. shadowInactive).",
+        "syncSchedule": "Розклад синхронізації",
+        "syncScheduleDesc": "Рядок типу cron, напр. @every 1m",
+        "inboundTags": "Теги вхідних",
+        "inboundTagsDesc": "Вхідні, на яких LDAP-синхронізація може авто-створювати або авто-видаляти клієнтів.",
+        "noInbounds": "Вхідних не знайдено. Спочатку створіть один у Вхідних.",
+        "autoCreate": "Авто-створення клієнтів",
+        "autoDelete": "Авто-видалення клієнтів",
+        "defaultTotalGb": "Обсяг за замовч. (ГБ)",
+        "defaultExpiryDays": "Термін за замовч. (дні)",
+        "defaultIpLimit": "Ліміт IP за замовч."
+      },
+      "subFormats": {
+        "packets": "Пакети",
+        "length": "Довжина",
+        "interval": "Інтервал",
+        "maxSplit": "Макс. розбиття",
+        "noises": "Шуми",
+        "noiseItem": "Шум №{n}",
+        "type": "Тип",
+        "packet": "Пакет",
+        "delayMs": "Затримка (мс)",
+        "applyTo": "Застосувати до",
+        "addNoise": "+ Шум",
+        "concurrency": "Паралельність",
+        "xudpConcurrency": "Паралельність xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Передавати кілька незалежних потоків даних у межах встановленого потоку даних.",
       "muxDesc": "Передавати кілька незалежних потоків даних у межах встановленого потоку даних.",
       "muxSett": "Налаштування Mux",
       "muxSett": "Налаштування Mux",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "Xray конфігурації",
       "title": "Xray конфігурації",
       "save": "Зберегти",
       "save": "Зберегти",
-      "restart": "Перезапустити Xray",
+      "restart": "Перезапуск Xray",
       "restartSuccess": "Xray успішно перезапущено",
       "restartSuccess": "Xray успішно перезапущено",
+      "restartOutputTitle": "Вивід перезапуску Xray",
+      "restartConfirmTitle": "Перезапустити xray?",
+      "restartConfirmContent": "Перезавантажує сервіс xray зі збереженою конфігурацією.",
       "stopSuccess": "Xray успішно зупинено",
       "stopSuccess": "Xray успішно зупинено",
       "restartError": "Виникла помилка під час перезапуску Xray.",
       "restartError": "Виникла помилка під час перезапуску Xray.",
       "stopError": "Виникла помилка під час зупинки Xray.",
       "stopError": "Виникла помилка під час зупинки Xray.",
@@ -765,7 +1069,7 @@
       "advancedTemplate": "Додатково",
       "advancedTemplate": "Додатково",
       "generalConfigs": "Загальні конфігурації",
       "generalConfigs": "Загальні конфігурації",
       "generalConfigsDesc": "Ці параметри визначатимуть загальні налаштування.",
       "generalConfigsDesc": "Ці параметри визначатимуть загальні налаштування.",
-      "logConfigs": "Журнал",
+      "logConfigs": "Лог",
       "logConfigsDesc": "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб",
       "logConfigsDesc": "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб",
       "blockConfigsDesc": "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів.",
       "blockConfigsDesc": "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів.",
       "basicRouting": "Основна Маршрутизація",
       "basicRouting": "Основна Маршрутизація",
@@ -792,8 +1096,10 @@
       "Torrent": "Блокувати протокол BitTorrent",
       "Torrent": "Блокувати протокол BitTorrent",
       "Inbounds": "Вхідні",
       "Inbounds": "Вхідні",
       "InboundsDesc": "Прийняття певних клієнтів.",
       "InboundsDesc": "Прийняття певних клієнтів.",
-      "Outbounds": "Вихід",
+      "Outbounds": "Вихідні",
       "Balancers": "Балансери",
       "Balancers": "Балансери",
+      "balancerTagRequired": "Тег обов'язковий",
+      "balancerSelectorRequired": "Виберіть принаймні один вихідний",
       "OutboundsDesc": "Встановити шлях вихідного трафіку.",
       "OutboundsDesc": "Встановити шлях вихідного трафіку.",
       "Routings": "Правила маршрутизації",
       "Routings": "Правила маршрутизації",
       "RoutingsDesc": "Пріоритет кожного правила важливий!",
       "RoutingsDesc": "Пріоритет кожного правила важливий!",
@@ -827,11 +1133,78 @@
         "inbound": "Вхідний",
         "inbound": "Вхідний",
         "outbound": "Вихідний",
         "outbound": "Вихідний",
         "balancer": "Балансувальник",
         "balancer": "Балансувальник",
-        "info": "Інформація",
+        "info": "Інфо",
         "add": "Додати правило",
         "add": "Додати правило",
         "edit": "Редагувати правило",
         "edit": "Редагувати правило",
         "useComma": "Елементи, розділені комами"
         "useComma": "Елементи, розділені комами"
       },
       },
+      "routing": {
+        "dragToReorder": "Перетягніть для зміни порядку"
+      },
+      "ruleForm": {
+        "sourceIps": "IP джерела",
+        "sourcePort": "Порт джерела",
+        "vlessRoute": "VLESS route",
+        "attributes": "Атрибути",
+        "value": "Значення",
+        "user": "Користувач",
+        "inboundTags": "Теги вхідних",
+        "outboundTag": "Тег вихідного",
+        "balancerTag": "Тег балансувальника",
+        "balancerTagTooltip": "Спрямовує трафік через один з налаштованих балансувальників навантаження"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Тег уже використовується іншим вихідним",
+        "tagRequired": "Тег обов'язковий",
+        "tagPlaceholder": "унікальний-тег",
+        "localIpPlaceholder": "локальний IP",
+        "addressRequired": "Адреса обов'язкова",
+        "portRequired": "Порт обов'язковий",
+        "optional": "опційно",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "Версія UoT",
+        "inboundTag": "Тег вхідного",
+        "inboundTagPlaceholder": "тег вхідного у правилах маршрутизації",
+        "responseType": "Тип відповіді",
+        "rewriteNetwork": "Переписати мережу",
+        "unchanged": "(без змін)",
+        "unchangedAddress": "(без змін) напр. 1.1.1.1",
+        "rules": "Правила",
+        "ruleN": "Правило {n}",
+        "action": "Дія",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Фінальні правила",
+        "overrideXrayPrivateIp": "Перевизначити дефолтний блок приватних IP у Xray",
+        "blockDelay": "Затримка блоку (мс)",
+        "reverseSniffing": "Зворотний sniffing",
+        "workers": "Воркери",
+        "reserved": "Зарезервовано",
+        "minUploadInterval": "Мін. інтервал завантаження (мс)",
+        "maxUploadSizeBytes": "Макс. розмір завантаження (байт)",
+        "uplinkChunkSize": "Розмір chunk Uplink",
+        "noGrpcHeader": "Без gRPC-заголовка",
+        "maxConcurrency": "Макс. паралельність",
+        "maxConnections": "Макс. з'єднань",
+        "maxReuseTimes": "Макс. повторних використань",
+        "maxRequestTimes": "Макс. запитів",
+        "maxReusableSecs": "Макс. секунд повторного використання",
+        "keepAlivePeriod": "Період keep alive",
+        "authPassword": "Пароль авторизації",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "ім'я сервера",
+        "verifyPeerName": "Перевіряти ім'я peer",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Інтервал keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Інтерфейс",
+        "ipv6Only": "Лише IPv6",
+        "acceptProxyProtocol": "Приймати proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (мс)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (с)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Додати вихідний",
         "addOutbound": "Додати вихідний",
         "addReverse": "Додати реверс",
         "addReverse": "Додати реверс",
@@ -846,8 +1219,8 @@
         "reverse": "Зворотний",
         "reverse": "Зворотний",
         "domain": "Домен",
         "domain": "Домен",
         "type": "Тип",
         "type": "Тип",
-        "bridge": "Міст",
-        "portal": "Портал",
+        "bridge": "Bridge",
+        "portal": "Portal",
         "link": "Посилання",
         "link": "Посилання",
         "intercon": "Взаємозв'язок",
         "intercon": "Взаємозв'язок",
         "settings": "Налаштування",
         "settings": "Налаштування",
@@ -860,6 +1233,8 @@
         "testSuccess": "Тест успішний",
         "testSuccess": "Тест успішний",
         "testFailed": "Тест не пройдено",
         "testFailed": "Тест не пройдено",
         "testError": "Не вдалося протестувати вихідне з'єднання",
         "testError": "Не вдалося протестувати вихідне з'єднання",
+        "testModeTooltip": "TCP: швидкий dial-only probe. HTTP: повний запит через xray.",
+        "testAll": "Тестувати всі",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Токен доступу",
         "accessToken": "Токен доступу",
         "country": "Країна",
         "country": "Країна",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "Селектори",
         "balancerSelectors": "Селектори",
         "tag": "Тег",
         "tag": "Тег",
         "tagDesc": "Унікальний тег",
         "tagDesc": "Унікальний тег",
+        "tagDuplicate": "Тег уже використовується іншим балансувальником",
+        "tagPlaceholder": "унікальний тег балансувальника",
+        "selector": "Селектор",
+        "fallback": "Fallback",
+        "expected": "Очікуване",
+        "expectedPlaceholder": "оптимальна кількість вузлів",
+        "maxRtt": "Макс. RTT",
+        "tolerance": "Допуск",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "Неможливо використовувати balancerTag і outboundTag одночасно. Якщо використовувати одночасно, працюватиме лише outboundTag."
         "balancerDesc": "Неможливо використовувати balancerTag і outboundTag одночасно. Якщо використовувати одночасно, працюватиме лише outboundTag."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Рівень користувача",
         "userLevel": "Рівень користувача",
         "userLevelDesc": "Всі з'єднання, встановлені через цей вхід, використовуватимуть цей рівень користувача. Значення за замовчуванням - 0"
         "userLevelDesc": "Всі з'єднання, встановлені через цей вхід, використовуватимуть цей рівень користувача. Значення за замовчуванням - 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Приватний ключ",
+        "noServers": "Серверів для обраної країни не знайдено",
+        "noPublicKey": "Обраний сервер не повідомляє публічного ключа NordLynx.",
+        "outboundAdded": "Вихідний NordVPN додано",
+        "outboundUpdated": "Вихідний NordVPN оновлено"
+      },
+      "warp": {
+        "licenseError": "Не вдалося встановити ліцензію WARP.",
+        "fetchFirst": "Спочатку отримайте WARP-конфіг.",
+        "createAccount": "Створити акаунт WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID пристрою",
+        "licenseKey": "Ключ ліцензії",
+        "privateKey": "Приватний ключ",
+        "deleteAccount": "Видалити акаунт",
+        "settings": "Налаштування",
+        "licenseKeyLabel": "Ключ ліцензії WARP / WARP+",
+        "key": "Ключ",
+        "keyPlaceholder": "26-символьний ключ WARP+",
+        "accountInfo": "Інформація про акаунт",
+        "deviceName": "Назва пристрою",
+        "deviceModel": "Модель пристрою",
+        "deviceEnabled": "Пристрій увімкнено",
+        "accountType": "Тип акаунта",
+        "role": "Роль",
+        "warpPlusData": "WARP+ data",
+        "quota": "Квота",
+        "usage": "Використання",
+        "addOutbound": "Додати вихідний"
+      },
       "dns": {
       "dns": {
         "enable": "Увімкнути DNS",
         "enable": "Увімкнути DNS",
         "enableDesc": "Увімкнути вбудований DNS-сервер",
         "enableDesc": "Увімкнути вбудований DNS-сервер",
@@ -961,8 +1378,8 @@
     "unknown": "Невідомо",
     "unknown": "Невідомо",
     "inbounds": "Вхідні",
     "inbounds": "Вхідні",
     "clients": "Клієнти",
     "clients": "Клієнти",
-    "offline": "🔴 Офлайн",
-    "online": "🟢 Онлайн",
+    "offline": "🔴 Не в мережі",
+    "online": "🟢 У мережі",
     "commands": {
     "commands": {
       "unknown": "❗ Невідома команда.",
       "unknown": "❗ Невідома команда.",
       "pleaseChoose": "👇 Будь ласка, виберіть:\r\n",
       "pleaseChoose": "👇 Будь ласка, виберіть:\r\n",
@@ -998,7 +1415,7 @@
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
-      "ips": "🔢 IP-адреси:\r\n{{ .IPs }}\r\n",
+      "ips": "🔢 IP:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ Час роботи: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ Час роботи: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 Завантаження системи: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 Завантаження системи: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
       "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
@@ -1009,7 +1426,7 @@
       "username": "👤 Ім'я користувача: {{ .Username }}\r\n",
       "username": "👤 Ім'я користувача: {{ .Username }}\r\n",
       "reason": "❗️ Причина: {{ .Reason }}\r\n",
       "reason": "❗️ Причина: {{ .Reason }}\r\n",
       "time": "⏰ Час: {{ .Time }}\r\n",
       "time": "⏰ Час: {{ .Time }}\r\n",
-      "inbound": "📍 Inbound: {{ .Remark }}\r\n",
+      "inbound": "📍 Вхідний: {{ .Remark }}\r\n",
       "port": "🔌 Порт: {{ .Port }}\r\n",
       "port": "🔌 Порт: {{ .Port }}\r\n",
       "expire": "📅 Дата закінчення: {{ .Time }}\r\n",
       "expire": "📅 Дата закінчення: {{ .Time }}\r\n",
       "expireIn": "📅 Термін дії: {{ .Time }}\r\n",
       "expireIn": "📅 Термін дії: {{ .Time }}\r\n",
@@ -1017,10 +1434,10 @@
       "enabled": "🚨 Увімкнено: {{ .Enable }}\r\n",
       "enabled": "🚨 Увімкнено: {{ .Enable }}\r\n",
       "online": "🌐 Стан підключення: {{ .Status }}\r\n",
       "online": "🌐 Стан підключення: {{ .Status }}\r\n",
       "lastOnline": "🔙 Був(ла) онлайн: {{ .Time }}\r\n",
       "lastOnline": "🔙 Був(ла) онлайн: {{ .Time }}\r\n",
-      "email": "📧 Електронна пошта: {{ .Email }}\r\n",
-      "upload": "🔼 Upload: ↑{{ .Upload }}\r\n",
-      "download": "🔽 Download: ↓{{ .Download }}\r\n",
-      "total": "📊 Всього: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
+      "email": "📧 Email: {{ .Email }}\r\n",
+      "upload": "🔼 Завантаження: ↑{{ .Upload }}\r\n",
+      "download": "🔽 Завантаження: ↓{{ .Download }}\r\n",
+      "total": "📊 Усього: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 Користувач Telegram: {{ .TelegramID }}\r\n",
       "TGUser": "👤 Користувач Telegram: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 Вичерпано {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 Вичерпано {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 Вичерпано кількість {{ .Type }} count:\r\n",
       "exhaustedCount": "🚨 Вичерпано кількість {{ .Type }} count:\r\n",
@@ -1077,7 +1494,7 @@
       "ipLimit": "🔢 IP Ліміт",
       "ipLimit": "🔢 IP Ліміт",
       "setTGUser": "👤 Встановити користувача Telegram",
       "setTGUser": "👤 Встановити користувача Telegram",
       "toggle": "🔘 Увімкнути / Вимкнути",
       "toggle": "🔘 Увімкнути / Вимкнути",
-      "custom": "🔢 Custom",
+      "custom": "🔢 Своє",
       "confirmNumber": "✅ Підтвердити: {{ .Num }}",
       "confirmNumber": "✅ Підтвердити: {{ .Num }}",
       "confirmNumberAdd": "✅ Підтвердити додавання: {{ .Num }}",
       "confirmNumberAdd": "✅ Підтвердити додавання: {{ .Num }}",
       "limitTraffic": "🚧 Ліміт трафіку",
       "limitTraffic": "🚧 Ліміт трафіку",
@@ -1089,9 +1506,9 @@
       "use_default": "🏷️ Використати типове",
       "use_default": "🏷️ Використати типове",
       "change_id": "⚙️🔑 ID",
       "change_id": "⚙️🔑 ID",
       "change_password": "⚙️🔑 Пароль",
       "change_password": "⚙️🔑 Пароль",
-      "change_email": "⚙️📧 Електронна пошта",
+      "change_email": "⚙️📧 Email",
       "change_comment": "⚙️💬 Коментар",
       "change_comment": "⚙️💬 Коментар",
-      "change_flow": "⚙️🚦 Потік",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "Скинути весь трафік",
       "ResetAllTraffics": "Скинути весь трафік",
       "SortedTrafficUsageReport": "Відсортований звіт про використання трафіку"
       "SortedTrafficUsageReport": "Відсортований звіт про використання трафіку"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Виберіть Вхідний"
       "chooseInbound": "Виберіть Вхідний"
     }
     }
   }
   }
-}
+}

+ 457 - 40
web/translation/vi-VN.json

@@ -8,15 +8,22 @@
   "save": "Lưu",
   "save": "Lưu",
   "logout": "Đăng xuất",
   "logout": "Đăng xuất",
   "create": "Tạo",
   "create": "Tạo",
+  "add": "Thêm",
+  "remove": "Xóa",
   "update": "Cập nhật",
   "update": "Cập nhật",
   "copy": "Sao chép",
   "copy": "Sao chép",
   "copied": "Đã sao chép",
   "copied": "Đã sao chép",
+  "more": "thêm",
   "download": "Tải xuống",
   "download": "Tải xuống",
   "remark": "Ghi chú",
   "remark": "Ghi chú",
   "enable": "Kích hoạt",
   "enable": "Kích hoạt",
   "protocol": "Giao thức",
   "protocol": "Giao thức",
   "search": "Tìm kiếm",
   "search": "Tìm kiếm",
-  "filter": "Bộ lọc",
+  "filter": "Lọc",
+  "all": "Tất cả",
+  "from": "Từ",
+  "to": "Đến",
+  "done": "Xong",
   "loading": "Đang tải",
   "loading": "Đang tải",
   "refresh": "Làm mới",
   "refresh": "Làm mới",
   "clear": "Xóa",
   "clear": "Xóa",
@@ -27,10 +34,10 @@
   "check": "Kiểm tra",
   "check": "Kiểm tra",
   "indefinite": "Không xác định",
   "indefinite": "Không xác định",
   "unlimited": "Không giới hạn",
   "unlimited": "Không giới hạn",
-  "none": "None",
+  "none": "Không",
   "qrCode": "Mã QR",
   "qrCode": "Mã QR",
   "info": "Thông tin thêm",
   "info": "Thông tin thêm",
-  "edit": "Chỉnh sửa",
+  "edit": "Sửa",
   "delete": "Xóa",
   "delete": "Xóa",
   "reset": "Đặt lại",
   "reset": "Đặt lại",
   "noData": "Không có dữ liệu.",
   "noData": "Không có dữ liệu.",
@@ -39,7 +46,7 @@
   "encryption": "Mã hóa",
   "encryption": "Mã hóa",
   "useIPv4ForHost": "Sử dụng IPv4 cho máy chủ",
   "useIPv4ForHost": "Sử dụng IPv4 cho máy chủ",
   "transmission": "Truyền tải",
   "transmission": "Truyền tải",
-  "host": "Máy chủ",
+  "host": "Host",
   "path": "Đường dẫn",
   "path": "Đường dẫn",
   "camouflage": "Ngụy trang",
   "camouflage": "Ngụy trang",
   "status": "Trạng thái",
   "status": "Trạng thái",
@@ -95,11 +102,12 @@
     "dark": "Tối",
     "dark": "Tối",
     "ultraDark": "Siêu tối",
     "ultraDark": "Siêu tối",
     "dashboard": "Trạng thái hệ thống",
     "dashboard": "Trạng thái hệ thống",
-    "inbounds": "Đầu vào khách hàng",
+    "inbounds": "Inbound",
     "clients": "Khách hàng",
     "clients": "Khách hàng",
+    "groups": "Nhóm",
     "nodes": "Nút",
     "nodes": "Nút",
     "settings": "Cài đặt bảng điều khiển",
     "settings": "Cài đặt bảng điều khiển",
-    "xray": "Cài đặt Xray",
+    "xray": "Cấu hình Xray",
     "apiDocs": "Tài liệu API",
     "apiDocs": "Tài liệu API",
     "logout": "Đăng xuất",
     "logout": "Đăng xuất",
     "link": "Quản lý",
     "link": "Quản lý",
@@ -128,7 +136,7 @@
       "memory": "RAM",
       "memory": "RAM",
       "threads": "Luồng",
       "threads": "Luồng",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
-      "stopXray": "Dừng lại",
+      "stopXray": "Dừng",
       "restartXray": "Khởi động lại",
       "restartXray": "Khởi động lại",
       "xraySwitch": "Phiên bản",
       "xraySwitch": "Phiên bản",
       "xrayUpdates": "Cập nhật Xray",
       "xrayUpdates": "Cập nhật Xray",
@@ -241,18 +249,18 @@
       "getConfigError": "Lỗi xảy ra khi truy xuất tệp cấu hình"
       "getConfigError": "Lỗi xảy ra khi truy xuất tệp cấu hình"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "Điểm vào (Inbounds)",
+      "title": "Inbound",
       "totalDownUp": "Tổng tải lên/tải xuống",
       "totalDownUp": "Tổng tải lên/tải xuống",
       "totalUsage": "Tổng sử dụng",
       "totalUsage": "Tổng sử dụng",
       "inboundCount": "Số lượng điểm vào",
       "inboundCount": "Số lượng điểm vào",
-      "operate": "Thao tác",
+      "operate": "Menu",
       "enable": "Kích hoạt",
       "enable": "Kích hoạt",
       "remark": "Chú thích",
       "remark": "Chú thích",
-      "node": "Nút",
+      "node": "Node",
       "deployTo": "Triển khai tới",
       "deployTo": "Triển khai tới",
       "localPanel": "Panel cục bộ",
       "localPanel": "Panel cục bộ",
       "fallbacks": {
       "fallbacks": {
-        "title": "Fallback",
+        "title": "Fallbacks",
         "help": "Khi một kết nối trên inbound này không khớp với client nào, nó sẽ được chuyển hướng tới inbound khác. Chọn một child bên dưới và các trường định tuyến (SNI / ALPN / Path / xver) sẽ được tự động điền từ transport của child — hầu hết cấu hình không cần chỉnh thêm. Mỗi child nên lắng nghe trên 127.0.0.1 với security=none.",
         "help": "Khi một kết nối trên inbound này không khớp với client nào, nó sẽ được chuyển hướng tới inbound khác. Chọn một child bên dưới và các trường định tuyến (SNI / ALPN / Path / xver) sẽ được tự động điền từ transport của child — hầu hết cấu hình không cần chỉnh thêm. Mỗi child nên lắng nghe trên 127.0.0.1 với security=none.",
         "empty": "Chưa có fallback nào",
         "empty": "Chưa có fallback nào",
         "add": "Thêm fallback",
         "add": "Thêm fallback",
@@ -270,10 +278,10 @@
       },
       },
       "protocol": "Giao thức",
       "protocol": "Giao thức",
       "port": "Cổng",
       "port": "Cổng",
-      "portMap": "Cổng tạo",
+      "portMap": "Ánh xạ cổng",
       "traffic": "Lưu lượng",
       "traffic": "Lưu lượng",
       "details": "Chi tiết",
       "details": "Chi tiết",
-      "transportConfig": "Giao vận",
+      "transportConfig": "Truyền dẫn",
       "expireDate": "Ngày hết hạn",
       "expireDate": "Ngày hết hạn",
       "createdAt": "Tạo lúc",
       "createdAt": "Tạo lúc",
       "updatedAt": "Cập nhật",
       "updatedAt": "Cập nhật",
@@ -292,6 +300,24 @@
       "delAllClients": "Xóa tất cả khách hàng",
       "delAllClients": "Xóa tất cả khách hàng",
       "delAllClientsConfirmTitle": "Xóa toàn bộ {count} khách hàng khỏi \"{remark}\"?",
       "delAllClientsConfirmTitle": "Xóa toàn bộ {count} khách hàng khỏi \"{remark}\"?",
       "delAllClientsConfirmContent": "Xóa mọi khách hàng khỏi inbound này và hủy bản ghi lưu lượng của họ. Bản thân inbound vẫn được giữ lại. Hành động này không thể hoàn tác.",
       "delAllClientsConfirmContent": "Xóa mọi khách hàng khỏi inbound này và hủy bản ghi lưu lượng của họ. Bản thân inbound vẫn được giữ lại. Hành động này không thể hoàn tác.",
+      "attachClients": "Gắn client vào…",
+      "addClientsToGroup": "Thêm client vào nhóm…",
+      "attachClientsTitle": "Gắn client từ «{remark}»",
+      "attachClientsDesc": "Gắn cùng {count} client (cùng UUID/mật khẩu và lưu lượng chung) vào các inbound đã chọn. Họ vẫn ở trên inbound này.",
+      "attachClientsTargets": "Inbound đích",
+      "attachClientsNoTargets": "Không có inbound tương thích khác để gắn.",
+      "attachClientsResult": "Đã gắn {attached}, bỏ qua {skipped}.",
+      "attachClientsResultMixed": "Đã gắn {attached}, bỏ qua {skipped}, lỗi {errors}.",
+      "attachClientsSelectLabel": "Client để gắn",
+      "attachClientsSearchPlaceholder": "Tìm email hoặc ghi chú",
+      "attachClientsStatusDisabled": "Đã tắt",
+      "attachClientsSelectedCount": "Đã chọn {selected}/{total}",
+      "detachClients": "Tách client",
+      "detachClientsTitle": "Tách client của «{remark}»",
+      "detachClientsDesc": "Chỉ xóa client đã chọn khỏi inbound này. Hồ sơ client được giữ lại (dùng Delete để xóa hoàn toàn). Nguồn có tổng cộng {count} client.",
+      "detachClientsResult": "Đã tách {detached}, bỏ qua {skipped}.",
+      "detachClientsResultMixed": "Đã tách {detached}, bỏ qua {skipped}, lỗi {errors}.",
+      "detachClientsSelectLabel": "Client để tách",
       "exportLinksTitle": "Xuất liên kết inbound",
       "exportLinksTitle": "Xuất liên kết inbound",
       "exportSubsTitle": "Xuất liên kết đăng ký",
       "exportSubsTitle": "Xuất liên kết đăng ký",
       "exportAllLinksTitle": "Xuất tất cả liên kết inbound",
       "exportAllLinksTitle": "Xuất tất cả liên kết inbound",
@@ -306,7 +332,7 @@
       "destinationPort": "Cổng đích",
       "destinationPort": "Cổng đích",
       "targetAddress": "Địa chỉ mục tiêu",
       "targetAddress": "Địa chỉ mục tiêu",
       "monitorDesc": "Mặc định để trống",
       "monitorDesc": "Mặc định để trống",
-      "meansNoLimit": "= Không giới hạn (đơn vị: GB)",
+      "meansNoLimit": "= Không giới hạn. (đơn vị: GB)",
       "totalFlow": "Tổng lưu lượng",
       "totalFlow": "Tổng lưu lượng",
       "leaveBlankToNeverExpire": "Để trống để không bao giờ hết hạn",
       "leaveBlankToNeverExpire": "Để trống để không bao giờ hết hạn",
       "noRecommendKeepDefault": "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định",
       "noRecommendKeepDefault": "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định",
@@ -341,6 +367,7 @@
       "IPLimitlogDesc": "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử).",
       "IPLimitlogDesc": "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử).",
       "IPLimitlogclear": "Xóa Lịch sử",
       "IPLimitlogclear": "Xóa Lịch sử",
       "setDefaultCert": "Đặt chứng chỉ từ bảng điều khiển",
       "setDefaultCert": "Đặt chứng chỉ từ bảng điều khiển",
+      "setDefaultCertEmpty": "Không có chứng chỉ nào được cấu hình cho bảng điều khiển. Hãy đặt một chứng chỉ trong Cài đặt trước.",
       "streamTab": "Stream",
       "streamTab": "Stream",
       "securityTab": "Bảo mật",
       "securityTab": "Bảo mật",
       "sniffingTab": "Sniffing",
       "sniffingTab": "Sniffing",
@@ -369,7 +396,6 @@
       },
       },
       "telegramDesc": "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc ({'@'}userinfobot)",
       "telegramDesc": "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc ({'@'}userinfobot)",
       "subscriptionDesc": "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau",
       "subscriptionDesc": "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau",
-      "info": "Thông tin",
       "same": "Giống nhau",
       "same": "Giống nhau",
       "inboundData": "Dữ liệu gửi đến",
       "inboundData": "Dữ liệu gửi đến",
       "exportInbound": "Xuất nhập khẩu",
       "exportInbound": "Xuất nhập khẩu",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "Lỗi khi lấy chứng chỉ mldsa65.",
         "getNewmldsa65Error": "Lỗi khi lấy chứng chỉ mldsa65.",
         "getNewVlessEncError": "Lỗi khi lấy chứng chỉ VlessEnc."
         "getNewVlessEncError": "Lỗi khi lấy chứng chỉ VlessEnc."
       },
       },
+      "form": {
+        "moveUp": "Lên",
+        "moveDown": "Xuống",
+        "addAll": "Thêm tất cả",
+        "addAllFallbackTooltip": "Thêm hàng fallback cho mỗi inbound đủ điều kiện chưa được nối",
+        "peers": "Peers",
+        "addPeer": "Thêm peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "Chỉ Windows. CIDR được tự động thêm vào bảng định tuyến hệ thống để lưu lượng khớp đi qua TUN.",
+        "autoOutboundsInterface": "Giao diện outbound tự động",
+        "autoOutboundsInterfaceTooltip": "Giao diện vật lý cho lưu lượng đi. Dùng 'auto' để tự phát hiện; tự bật khi Auto system routes được đặt.",
+        "rewriteAddress": "Viết lại địa chỉ",
+        "rewritePort": "Viết lại cổng",
+        "allowedNetwork": "Mạng cho phép",
+        "followRedirect": "Theo redirect",
+        "accounts": "Tài khoản",
+        "allowTransparent": "Cho phép trong suốt",
+        "encryptionMethod": "Phương thức mã hóa",
+        "visionTestseed": "Vision testseed",
+        "version": "Phiên bản",
+        "udpIdleTimeout": "UDP idle timeout (s)",
+        "masquerade": "Masquerade",
+        "type": "Loại",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "Viết lại Host",
+        "skipTlsVerify": "Bỏ qua xác minh TLS",
+        "directory": "Thư mục",
+        "statusCode": "Mã trạng thái",
+        "body": "Body",
+        "headers": "Header",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "Phiên bản yêu cầu",
+        "requestMethod": "Phương thức yêu cầu",
+        "requestPath": "Đường dẫn yêu cầu",
+        "requestHeaders": "Header yêu cầu",
+        "responseVersion": "Phiên bản phản hồi",
+        "responseStatus": "Trạng thái phản hồi",
+        "responseReason": "Lý do phản hồi",
+        "responseHeaders": "Header phản hồi",
+        "heartbeatPeriod": "Chu kỳ heartbeat",
+        "serviceName": "Tên dịch vụ",
+        "authority": "Authority",
+        "multiMode": "Multi Mode",
+        "maxBufferedUpload": "Upload buffered tối đa",
+        "maxUploadSize": "Kích thước upload tối đa (Byte)",
+        "streamUpServer": "Stream-Up Server",
+        "serverMaxHeaderBytes": "Byte header máy chủ tối đa",
+        "paddingBytes": "Byte Padding",
+        "uplinkHttpMethod": "Uplink HTTP method",
+        "paddingObfsMode": "Chế độ obfs Padding",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Vị trí Padding",
+        "paddingMethod": "Phương thức Padding",
+        "sessionPlacement": "Session Placement",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence Placement",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink Data Placement",
+        "uplinkDataKey": "Uplink Data Key",
+        "noSseHeader": "Không có header SSE",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "Uplink (MB/s)",
+        "downlinkMbps": "Downlink (MB/s)",
+        "cwndMultiplier": "Hệ số CWND",
+        "maxSendingWindow": "Cửa sổ gửi tối đa",
+        "externalProxy": "Proxy ngoài",
+        "sniPlaceholder": "SNI (mặc định = host)",
+        "fingerprint": "Fingerprint",
+        "defaultOption": "Mặc định",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive Interval",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "Chỉ V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "X-Forwarded-For tin cậy",
+        "addressPortStrategy": "Chiến lược địa chỉ+cổng",
+        "tryDelayMs": "Độ trễ thử (ms)",
+        "prioritizeIPv6": "Ưu tiên IPv6",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "Số thử đồng thời tối đa",
+        "customSockopt": "Sockopt tùy chỉnh",
+        "addCustomOption": "Thêm tùy chọn",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "Tự động",
+        "minMaxVersion": "Phiên bản Min/Max",
+        "rejectUnknownSni": "Từ chối SNI lạ",
+        "disableSystemRoot": "Tắt System Root",
+        "sessionResumption": "Khôi phục phiên",
+        "oneTimeLoading": "Tải một lần",
+        "usageOption": "Tùy chọn sử dụng",
+        "buildChain": "Tạo chuỗi",
+        "echKey": "ECH key",
+        "echConfig": "Cấu hình ECH",
+        "getNewEchCert": "Lấy chứng chỉ ECH mới",
+        "show": "Hiện",
+        "xver": "Xver",
+        "target": "Mục tiêu",
+        "maxTimeDiff": "Chênh lệch thời gian tối đa (ms)",
+        "minClientVer": "Phiên bản client tối thiểu",
+        "maxClientVer": "Phiên bản client tối đa",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "Lấy chứng chỉ mới",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "Lấy Seed mới"
+      },
+      "info": {
+        "mode": "Chế độ",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "Tên giao diện",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "Giao diện outbound",
+        "autoSystemRoutes": "Định tuyến hệ thống tự động",
+        "followRedirect": "FollowRedirect",
+        "auth": "Auth",
+        "noKernelTun": "TUN không kernel",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Cấu hình Peer {n}"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "Lời yêu cầu",
           "request": "Lời yêu cầu",
@@ -456,6 +615,20 @@
       "days": "Ngày",
       "days": "Ngày",
       "renew": "Tự động gia hạn",
       "renew": "Tự động gia hạn",
       "renewDesc": "Tự động gia hạn sau khi hết hạn. (0 = tắt) (đơn vị: ngày)",
       "renewDesc": "Tự động gia hạn sau khi hết hạn. (0 = tắt) (đơn vị: ngày)",
+      "searchPlaceholder": "Tìm email, ghi chú, sub ID, UUID, mật khẩu, auth…",
+      "filterTitle": "Lọc client",
+      "clearAllFilters": "Xóa tất cả",
+      "sortOldest": "Cũ nhất trước",
+      "sortNewest": "Mới nhất trước",
+      "sortRecentlyUpdated": "Gần đây cập nhật",
+      "sortRecentlyOnline": "Gần đây trực tuyến",
+      "sortEmailAZ": "Email A→Z",
+      "sortEmailZA": "Email Z→A",
+      "sortMostTraffic": "Nhiều lưu lượng nhất",
+      "sortHighestRemaining": "Còn nhiều nhất",
+      "sortExpiringSoonest": "Sắp hết hạn",
+      "has": "Có",
+      "hasNot": "Không có",
       "title": "Khách hàng",
       "title": "Khách hàng",
       "actions": "Hành động",
       "actions": "Hành động",
       "totalGB": "Tổng gửi/nhận (GB)",
       "totalGB": "Tổng gửi/nhận (GB)",
@@ -466,6 +639,9 @@
       "subId": "ID đăng ký",
       "subId": "ID đăng ký",
       "online": "Trực tuyến",
       "online": "Trực tuyến",
       "email": "Email",
       "email": "Email",
+      "group": "Nhóm",
+      "groupDesc": "Nhãn logic để gom các client liên quan (nhóm, khách hàng, khu vực). Có thể lọc từ thanh công cụ.",
+      "groupPlaceholder": "ví dụ customer-a",
       "comment": "Ghi chú",
       "comment": "Ghi chú",
       "traffic": "Lưu lượng",
       "traffic": "Lưu lượng",
       "offline": "Ngoại tuyến",
       "offline": "Ngoại tuyến",
@@ -489,11 +665,45 @@
       "resetAllTraffics": "Đặt lại lưu lượng của tất cả khách hàng",
       "resetAllTraffics": "Đặt lại lưu lượng của tất cả khách hàng",
       "resetAllTrafficsTitle": "Đặt lại lưu lượng của tất cả khách hàng?",
       "resetAllTrafficsTitle": "Đặt lại lưu lượng của tất cả khách hàng?",
       "resetAllTrafficsContent": "Bộ đếm gửi/nhận của mỗi khách hàng về 0. Hạn mức và thời hạn không bị ảnh hưởng. Không thể hoàn tác.",
       "resetAllTrafficsContent": "Bộ đếm gửi/nhận của mỗi khách hàng về 0. Hạn mức và thời hạn không bị ảnh hưởng. Không thể hoàn tác.",
-      "empty": "Chưa có khách hàng nào — thêm một để bắt đầu.",
       "deleteConfirmTitle": "Xóa khách hàng {email}?",
       "deleteConfirmTitle": "Xóa khách hàng {email}?",
       "deleteConfirmContent": "Hành động này gỡ khách hàng khỏi mọi inbound đã gắn và xóa bản ghi lưu lượng. Không thể hoàn tác.",
       "deleteConfirmContent": "Hành động này gỡ khách hàng khỏi mọi inbound đã gắn và xóa bản ghi lưu lượng. Không thể hoàn tác.",
       "deleteSelected": "Xóa ({count})",
       "deleteSelected": "Xóa ({count})",
       "adjustSelected": "Điều chỉnh ({count})",
       "adjustSelected": "Điều chỉnh ({count})",
+      "subLinksSelected": "Liên kết sub ({count})",
+      "addToGroupTitle": "Thêm {count} client vào một nhóm",
+      "addToGroupTooltip": "Chọn nhóm có sẵn hoặc nhập tên mới. Dùng Ungroup để xóa client khỏi nhóm hiện tại.",
+      "addToGroupPlaceholder": "Tên nhóm",
+      "addToGroupSuccessToast": "Đã thêm {count} client vào {group}",
+      "ungroupSuccessToast": "Đã xóa nhóm khỏi {count} client",
+      "ungroup": "Bỏ nhóm",
+      "ungroupConfirmTitle": "Xóa {count} client khỏi nhóm của họ?",
+      "ungroupConfirmContent": "Xóa nhãn nhóm trên mỗi client đã chọn. Bản thân client được giữ lại (dùng Delete để xóa hoàn toàn).",
+      "addToGroup": "Thêm vào nhóm",
+      "attach": "Gắn",
+      "adjust": "Điều chỉnh",
+      "subLinks": "Liên kết sub",
+      "selectedCount": "Đã chọn {count}",
+      "attachSelected": "Gắn ({count})",
+      "attachToInboundsTitle": "Gắn {count} client vào inbound",
+      "attachToInboundsDesc": "Gắn {count} client đã chọn (cùng UUID/mật khẩu và lưu lượng chung) vào các inbound đã chọn. Các gắn kết hiện tại được giữ nguyên.",
+      "attachToInboundsTargets": "Inbound đích",
+      "attachToInboundsNoTargets": "Không có inbound đa người dùng nào để gắn.",
+      "detachSelected": "Tách ({count})",
+      "detach": "Tách",
+      "detachFromInboundsTitle": "Tách {count} client khỏi inbound",
+      "detachFromInboundsDesc": "Xóa {count} client đã chọn khỏi các inbound đã chọn. Các cặp client chưa gắn sẽ được bỏ qua. Hồ sơ client được giữ lại (dùng Delete để xóa hoàn toàn).",
+      "detachFromInboundsTargets": "Inbound để tách",
+      "detachFromInboundsNoTargets": "Không có inbound đa người dùng nào.",
+      "detachFromInboundsResult": "Đã tách {detached}, bỏ qua {skipped}.",
+      "detachFromInboundsResultMixed": "Đã tách {detached}, bỏ qua {skipped}, lỗi {errors}.",
+      "subLinksTitle": "Liên kết sub ({count})",
+      "subLinkColumn": "URL đăng ký",
+      "subJsonLinkColumn": "URL JSON đăng ký",
+      "subLinksCopyAll": "Sao chép tất cả",
+      "subLinksCopiedAll": "Đã sao chép {count} liên kết",
+      "subLinksEmpty": "Không client nào trong các client đã chọn có ID đăng ký.",
+      "subLinksDisabled": "Dịch vụ đăng ký đã tắt.",
+      "subLinksDisabledHint": "Bật đăng ký tại Cài đặt bảng điều khiển → Đăng ký để tạo liên kết.",
       "bulkDeleteConfirmTitle": "Xóa {count} khách hàng?",
       "bulkDeleteConfirmTitle": "Xóa {count} khách hàng?",
       "bulkDeleteConfirmContent": "Mỗi khách hàng được chọn sẽ bị gỡ khỏi tất cả inbound đã gắn và bản ghi lưu lượng cũng bị xóa. Không thể hoàn tác.",
       "bulkDeleteConfirmContent": "Mỗi khách hàng được chọn sẽ bị gỡ khỏi tất cả inbound đã gắn và bản ghi lưu lượng cũng bị xóa. Không thể hoàn tác.",
       "bulkAdjustTitle": "Điều chỉnh {count} khách hàng",
       "bulkAdjustTitle": "Điều chỉnh {count} khách hàng",
@@ -505,9 +715,10 @@
       "delDepletedConfirmTitle": "Xóa khách hàng hết hạn mức?",
       "delDepletedConfirmTitle": "Xóa khách hàng hết hạn mức?",
       "delDepletedConfirmContent": "Gỡ tất cả khách hàng đã dùng hết hạn mức lưu lượng hoặc đã quá hạn. Không thể hoàn tác.",
       "delDepletedConfirmContent": "Gỡ tất cả khách hàng đã dùng hết hạn mức lưu lượng hoặc đã quá hạn. Không thể hoàn tác.",
       "auth": "Auth",
       "auth": "Auth",
-      "hysteriaAuth": "Auth Hysteria",
+      "hysteriaAuth": "Hysteria Auth",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
+      "vmessSecurity": "Bảo mật VMess",
       "reverseTag": "Reverse tag",
       "reverseTag": "Reverse tag",
       "reverseTagPlaceholder": "Reverse tag tùy chọn",
       "reverseTagPlaceholder": "Reverse tag tùy chọn",
       "telegramId": "ID người dùng Telegram",
       "telegramId": "ID người dùng Telegram",
@@ -528,10 +739,48 @@
         "delDepleted": "Đã xóa {count} khách hàng hết hạn mức"
         "delDepleted": "Đã xóa {count} khách hàng hết hạn mức"
       }
       }
     },
     },
+    "groups": {
+      "title": "Nhóm",
+      "name": "Tên",
+      "clientCount": "Client trong nhóm",
+      "totalGroups": "Tổng số nhóm",
+      "totalGroupedClients": "Client có nhóm",
+      "emptyGroups": "Nhóm trống",
+      "addGroup": "Thêm nhóm",
+      "createSuccess": "Đã tạo nhóm «{name}».",
+      "rename": "Đổi tên",
+      "renameTitle": "Đổi tên {name}",
+      "renameCollision": "Nhóm có tên «{name}» đã tồn tại.",
+      "renameSuccess": "Đã đổi tên nhóm trên {count} client.",
+      "deleteConfirmTitle": "Xóa nhóm {name}?",
+      "deleteConfirmContent": "Việc này xóa nhóm và xóa nhãn khỏi {count} client. Bản thân client không bị xóa.",
+      "deleteSuccess": "Đã xóa nhóm khỏi {count} client.",
+      "resetTraffic": "Đặt lại lưu lượng",
+      "resetConfirmTitle": "Đặt lại lưu lượng nhóm {name}?",
+      "resetConfirmContent": "Việc này đưa up/down về 0 cho tất cả {count} client trong nhóm.",
+      "resetSuccess": "Đã đặt lại lưu lượng cho {count} client.",
+      "adjustSuccess": "Đã điều chỉnh {count} client trong {name}.",
+      "emptyForAction": "Nhóm này chưa có client.",
+      "deleteGroupOnly": "Xóa nhóm (giữ client)",
+      "deleteClients": "Xóa client trong nhóm",
+      "deleteClientsConfirmTitle": "Xóa tất cả client trong {name}?",
+      "deleteClientsConfirmContent": "Việc này xóa vĩnh viễn {count} client cùng với hồ sơ lưu lượng. Nhãn nhóm cũng được xóa. Không thể hoàn tác.",
+      "deleteClientsSuccess": "Đã xóa {count} client.",
+      "deleteClientsMixed": "{ok} đã xóa, {failed} bỏ qua",
+      "addToGroup": "Thêm client…",
+      "addToGroupTitle": "Thêm client vào nhóm «{name}»",
+      "addToGroupDesc": "Chọn client để thêm vào nhóm này. Giữ nguyên gắn kết inbound hiện tại; chỉ thay đổi nhãn nhóm. Client đã ở trong nhóm này sẽ không được liệt kê.",
+      "addToGroupEmpty": "Không có client khác để thêm.",
+      "addToGroupResult": "Đã thêm {count} client vào {name}.",
+      "removeFromGroup": "Xóa client…",
+      "removeFromGroupTitle": "Xóa client khỏi nhóm «{name}»",
+      "removeFromGroupDesc": "Chọn thành viên để xóa khỏi nhóm này. Bản thân client được giữ lại (dùng «Xóa client trong nhóm» để xóa hoàn toàn).",
+      "removeFromGroupResult": "Đã xóa {count} client khỏi {name}."
+    },
     "nodes": {
     "nodes": {
       "title": "Nút",
       "title": "Nút",
       "addNode": "Thêm nút",
       "addNode": "Thêm nút",
-      "editNode": "Chỉnh sửa nút",
+      "editNode": "Sửa node",
       "totalNodes": "Tổng số nút",
       "totalNodes": "Tổng số nút",
       "onlineNodes": "Trực tuyến",
       "onlineNodes": "Trực tuyến",
       "offlineNodes": "Ngoại tuyến",
       "offlineNodes": "Ngoại tuyến",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu từ '/')",
       "publicKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu từ '/')",
       "privateKeyPath": "Đường dẫn file khóa của chứng chỉ bảng điều khiển",
       "privateKeyPath": "Đường dẫn file khóa của chứng chỉ bảng điều khiển",
       "privateKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu từ '/')",
       "privateKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu từ '/')",
-      "panelUrlPath": "Đường dẫn gốc URL bảng điều khiển",
+      "panelUrlPath": "Đường dẫn URI",
       "panelUrlPathDesc": "Phải bắt đầu và kết thúc bằng '/'",
       "panelUrlPathDesc": "Phải bắt đầu và kết thúc bằng '/'",
       "pageSize": "Kích thước phân trang",
       "pageSize": "Kích thước phân trang",
       "pageSizeDesc": "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt",
       "pageSizeDesc": "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt",
+      "panelProxy": "Proxy mạng của bảng điều khiển",
+      "panelProxyDesc": "Định tuyến các yêu cầu đi của chính bảng điều khiển (cập nhật geo, kiểm tra phiên bản Xray/panel, Telegram) qua proxy này để vượt qua lọc GitHub/Telegram phía máy chủ. Chấp nhận socks5:// hoặc http(s)://, ví dụ inbound SOCKS cục bộ của Xray. Để trống để kết nối trực tiếp.",
       "remarkModel": "Ghi chú mô hình và ký tự phân tách",
       "remarkModel": "Ghi chú mô hình và ký tự phân tách",
       "datepicker": "Kiểu lịch",
       "datepicker": "Kiểu lịch",
       "datepickerPlaceholder": "Chọn ngày",
       "datepickerPlaceholder": "Chọn ngày",
@@ -632,9 +883,9 @@
       "telegramBotEnableDesc": "Kết nối với các tính năng của bảng điều khiển này thông qua bot Telegram",
       "telegramBotEnableDesc": "Kết nối với các tính năng của bảng điều khiển này thông qua bot Telegram",
       "telegramToken": "Token Telegram",
       "telegramToken": "Token Telegram",
       "telegramTokenDesc": "Bạn phải nhận token từ quản lý bot Telegram {'@'}botfather",
       "telegramTokenDesc": "Bạn phải nhận token từ quản lý bot Telegram {'@'}botfather",
-      "telegramProxy": "Socks5 Proxy",
+      "telegramProxy": "SOCKS Proxy",
       "telegramProxyDesc": "Nếu bạn cần socks5 proxy để kết nối với Telegram. Điều chỉnh cài đặt của nó theo hướng dẫn.",
       "telegramProxyDesc": "Nếu bạn cần socks5 proxy để kết nối với Telegram. Điều chỉnh cài đặt của nó theo hướng dẫn.",
-      "telegramAPIServer": "Telegram API Server",
+      "telegramAPIServer": "Máy chủ API Telegram",
       "telegramAPIServerDesc": "Máy chủ API Telegram để sử dụng. Để trống để sử dụng máy chủ mặc định.",
       "telegramAPIServerDesc": "Máy chủ API Telegram để sử dụng. Để trống để sử dụng máy chủ mặc định.",
       "telegramChatId": "Chat ID Telegram của quản trị viên",
       "telegramChatId": "Chat ID Telegram của quản trị viên",
       "telegramChatIdDesc": "Nhiều Chat ID phân tách bằng dấu phẩy. Sử dụng {'@'}userinfobot hoặc sử dụng lệnh '/id' trong bot để lấy Chat ID của bạn.",
       "telegramChatIdDesc": "Nhiều Chat ID phân tách bằng dấu phẩy. Sử dụng {'@'}userinfobot hoặc sử dụng lệnh '/id' trong bot để lấy Chat ID của bạn.",
@@ -658,6 +909,8 @@
       "subEnable": "Bật dịch vụ",
       "subEnable": "Bật dịch vụ",
       "subEnableDesc": "Tính năng gói đăng ký với cấu hình riêng",
       "subEnableDesc": "Tính năng gói đăng ký với cấu hình riêng",
       "subJsonEnable": "Bật/Tắt điểm cuối đăng ký JSON độc lập.",
       "subJsonEnable": "Bật/Tắt điểm cuối đăng ký JSON độc lập.",
+      "subJsonEnableTitle": "Đăng ký JSON",
+      "subClashEnableTitle": "Đăng ký Clash / Mihomo",
       "subTitle": "Tiêu đề Đăng ký",
       "subTitle": "Tiêu đề Đăng ký",
       "subTitleDesc": "Tiêu đề hiển thị trong ứng dụng VPN",
       "subTitleDesc": "Tiêu đề hiển thị trong ứng dụng VPN",
       "subSupportUrl": "URL Hỗ trợ",
       "subSupportUrl": "URL Hỗ trợ",
@@ -678,13 +931,13 @@
       "subCertPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu với '/')",
       "subCertPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu với '/')",
       "subKeyPath": "Đường dẫn file khóa của chứng chỉ gói đăng ký",
       "subKeyPath": "Đường dẫn file khóa của chứng chỉ gói đăng ký",
       "subKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu với '/')",
       "subKeyPathDesc": "Điền vào đường dẫn đầy đủ (bắt đầu với '/')",
-      "subPath": "Đường dẫn gốc URL gói đăng ký",
+      "subPath": "Đường dẫn URI",
       "subPathDesc": "Phải bắt đầu và kết thúc bằng '/'",
       "subPathDesc": "Phải bắt đầu và kết thúc bằng '/'",
       "subDomain": "Tên miền con",
       "subDomain": "Tên miền con",
       "subDomainDesc": "Mặc định để trống để nghe tất cả các tên miền và IP",
       "subDomainDesc": "Mặc định để trống để nghe tất cả các tên miền và IP",
       "subUpdates": "Khoảng thời gian cập nhật gói đăng ký",
       "subUpdates": "Khoảng thời gian cập nhật gói đăng ký",
       "subUpdatesDesc": "Số giờ giữa các cập nhật trong ứng dụng khách",
       "subUpdatesDesc": "Số giờ giữa các cập nhật trong ứng dụng khách",
-      "subEncrypt": "Mã hóa cấu hình",
+      "subEncrypt": "Mã hóa",
       "subEncryptDesc": "Mã hóa các cấu hình được trả về trong gói đăng ký",
       "subEncryptDesc": "Mã hóa các cấu hình được trả về trong gói đăng ký",
       "subShowInfo": "Hiển thị thông tin sử dụng",
       "subShowInfo": "Hiển thị thông tin sử dụng",
       "subShowInfoDesc": "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình",
       "subShowInfoDesc": "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình",
@@ -693,7 +946,7 @@
       "subURI": "URI proxy trung gian",
       "subURI": "URI proxy trung gian",
       "subURIDesc": "Thay đổi URI cơ sở của URL gói đăng ký để sử dụng cho proxy trung gian",
       "subURIDesc": "Thay đổi URI cơ sở của URL gói đăng ký để sử dụng cho proxy trung gian",
       "externalTrafficInformEnable": "Thông báo giao thông bên ngoài",
       "externalTrafficInformEnable": "Thông báo giao thông bên ngoài",
-      "externalTrafficInformEnableDesc": "Thông báo cho API bên ngoài về mọi cập nhật lưu lượng truy cập.",
+      "externalTrafficInformEnableDesc": "Thông báo API ngoài mỗi khi cập nhật lưu lượng.",
       "externalTrafficInformURI": "URI thông báo lưu lượng truy cập bên ngoài",
       "externalTrafficInformURI": "URI thông báo lưu lượng truy cập bên ngoài",
       "externalTrafficInformURIDesc": "Cập nhật lưu lượng truy cập được gửi tới URI này.",
       "externalTrafficInformURIDesc": "Cập nhật lưu lượng truy cập được gửi tới URI này.",
       "restartXrayOnClientDisable": "Khởi Động Lại Xray Sau Khi Tự Động Vô Hiệu Hóa",
       "restartXrayOnClientDisable": "Khởi Động Lại Xray Sau Khi Tự Động Vô Hiệu Hóa",
@@ -703,6 +956,54 @@
       "fragmentSett": "Cài đặt phân mảnh",
       "fragmentSett": "Cài đặt phân mảnh",
       "noisesDesc": "Bật Noises.",
       "noisesDesc": "Bật Noises.",
       "noisesSett": "Cài đặt Noises",
       "noisesSett": "Cài đặt Noises",
+      "trustedProxyCidrs": "CIDR proxy tin cậy",
+      "trustedProxyCidrsDesc": "IPs/CIDRs cách nhau bằng dấu phẩy được phép đặt header host, proto và IP client chuyển tiếp.",
+      "ldap": {
+        "enable": "Bật đồng bộ LDAP",
+        "host": "LDAP host",
+        "port": "Cổng LDAP",
+        "useTls": "Dùng TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "Đã cấu hình; để trống để giữ mật khẩu hiện tại.",
+        "passwordUnconfigured": "Chưa cấu hình.",
+        "passwordPlaceholder": "Đã cấu hình — nhập giá trị mới để thay thế",
+        "baseDn": "Base DN",
+        "userFilter": "Bộ lọc user",
+        "userAttr": "Thuộc tính user (username/email)",
+        "vlessField": "Thuộc tính flag VLESS",
+        "flagField": "Thuộc tính flag chung (tùy chọn)",
+        "flagFieldDesc": "Nếu đặt, sẽ ghi đè VLESS flag — ví dụ shadowInactive.",
+        "truthyValues": "Giá trị truthy",
+        "truthyValuesDesc": "Cách nhau bằng dấu phẩy; mặc định: true,1,yes,on",
+        "invertFlag": "Đảo flag",
+        "invertFlagDesc": "Bật khi thuộc tính có nghĩa «đã tắt» (ví dụ shadowInactive).",
+        "syncSchedule": "Lịch đồng bộ",
+        "syncScheduleDesc": "Chuỗi kiểu cron, ví dụ @every 1m",
+        "inboundTags": "Tag inbound",
+        "inboundTagsDesc": "Các inbound mà đồng bộ LDAP có thể tự tạo hoặc tự xóa client.",
+        "noInbounds": "Không tìm thấy inbound. Hãy tạo một inbound trong mục Inbound trước.",
+        "autoCreate": "Tự động tạo client",
+        "autoDelete": "Tự động xóa client",
+        "defaultTotalGb": "Tổng mặc định (GB)",
+        "defaultExpiryDays": "Hết hạn mặc định (ngày)",
+        "defaultIpLimit": "Giới hạn IP mặc định"
+      },
+      "subFormats": {
+        "packets": "Gói",
+        "length": "Độ dài",
+        "interval": "Khoảng",
+        "maxSplit": "Chia tối đa",
+        "noises": "Nhiễu",
+        "noiseItem": "Nhiễu №{n}",
+        "type": "Loại",
+        "packet": "Gói",
+        "delayMs": "Trễ (ms)",
+        "applyTo": "Áp dụng cho",
+        "addNoise": "+ Nhiễu",
+        "concurrency": "Đồng thời",
+        "xudpConcurrency": "Đồng thời xudp",
+        "xudpUdp443": "xudp UDP 443"
+      },
       "mux": "Mux",
       "mux": "Mux",
       "muxDesc": "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập.",
       "muxDesc": "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập.",
       "muxSett": "Mux Cài đặt",
       "muxSett": "Mux Cài đặt",
@@ -758,6 +1059,9 @@
       "save": "Lưu cài đặt",
       "save": "Lưu cài đặt",
       "restart": "Khởi động lại Xray",
       "restart": "Khởi động lại Xray",
       "restartSuccess": "Đã khởi động lại Xray thành công",
       "restartSuccess": "Đã khởi động lại Xray thành công",
+      "restartOutputTitle": "Đầu ra khởi động lại Xray",
+      "restartConfirmTitle": "Khởi động lại xray?",
+      "restartConfirmContent": "Tải lại dịch vụ xray với cấu hình đã lưu.",
       "stopSuccess": "Xray đã được dừng thành công",
       "stopSuccess": "Xray đã được dừng thành công",
       "restartError": "Đã xảy ra lỗi khi khởi động lại Xray.",
       "restartError": "Đã xảy ra lỗi khi khởi động lại Xray.",
       "stopError": "Đã xảy ra lỗi khi dừng Xray.",
       "stopError": "Đã xảy ra lỗi khi dừng Xray.",
@@ -790,14 +1094,16 @@
       "outboundTestUrl": "URL kiểm tra outbound",
       "outboundTestUrl": "URL kiểm tra outbound",
       "outboundTestUrlDesc": "URL dùng khi kiểm tra kết nối outbound",
       "outboundTestUrlDesc": "URL dùng khi kiểm tra kết nối outbound",
       "Torrent": "Cấu hình sử dụng BitTorrent",
       "Torrent": "Cấu hình sử dụng BitTorrent",
-      "Inbounds": "Đầu vào",
+      "Inbounds": "Inbound",
       "InboundsDesc": "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể.",
       "InboundsDesc": "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể.",
-      "Outbounds": "Đầu ra",
+      "Outbounds": "Outbound",
       "Balancers": "Cân bằng",
       "Balancers": "Cân bằng",
+      "balancerTagRequired": "Tag là bắt buộc",
+      "balancerSelectorRequired": "Chọn ít nhất một outbound",
       "OutboundsDesc": "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này.",
       "OutboundsDesc": "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này.",
       "Routings": "Quy tắc định tuyến",
       "Routings": "Quy tắc định tuyến",
       "RoutingsDesc": "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!",
       "RoutingsDesc": "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!",
-      "completeTemplate": "All",
+      "completeTemplate": "Tất cả",
       "logLevel": "Mức đăng nhập",
       "logLevel": "Mức đăng nhập",
       "logLevelDesc": "Cấp độ nhật ký cho nhật ký lỗi, cho biết thông tin cần được ghi lại.",
       "logLevelDesc": "Cấp độ nhật ký cho nhật ký lỗi, cho biết thông tin cần được ghi lại.",
       "accessLog": "Nhật ký truy cập",
       "accessLog": "Nhật ký truy cập",
@@ -832,6 +1138,73 @@
         "edit": "Chỉnh sửa quy tắc",
         "edit": "Chỉnh sửa quy tắc",
         "useComma": "Các mục được phân tách bằng dấu phẩy"
         "useComma": "Các mục được phân tách bằng dấu phẩy"
       },
       },
+      "routing": {
+        "dragToReorder": "Kéo để sắp xếp lại"
+      },
+      "ruleForm": {
+        "sourceIps": "IP nguồn",
+        "sourcePort": "Cổng nguồn",
+        "vlessRoute": "Đường VLESS",
+        "attributes": "Thuộc tính",
+        "value": "Giá trị",
+        "user": "Người dùng",
+        "inboundTags": "Tag inbound",
+        "outboundTag": "Tag outbound",
+        "balancerTag": "Tag balancer",
+        "balancerTagTooltip": "Định tuyến lưu lượng qua một trong các bộ cân bằng tải đã cấu hình"
+      },
+      "outboundForm": {
+        "tagDuplicate": "Tag đã được dùng bởi outbound khác",
+        "tagRequired": "Tag là bắt buộc",
+        "tagPlaceholder": "tag-duy-nhất",
+        "localIpPlaceholder": "IP nội bộ",
+        "addressRequired": "Địa chỉ là bắt buộc",
+        "portRequired": "Cổng là bắt buộc",
+        "optional": "tùy chọn",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "Phiên bản UoT",
+        "inboundTag": "Tag inbound",
+        "inboundTagPlaceholder": "tag inbound dùng trong quy tắc định tuyến",
+        "responseType": "Loại phản hồi",
+        "rewriteNetwork": "Viết lại mạng",
+        "unchanged": "(không đổi)",
+        "unchangedAddress": "(không đổi) ví dụ 1.1.1.1",
+        "rules": "Quy tắc",
+        "ruleN": "Quy tắc {n}",
+        "action": "Hành động",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "Quy tắc cuối",
+        "overrideXrayPrivateIp": "Ghi đè chặn IP riêng mặc định của Xray",
+        "blockDelay": "Trễ chặn (ms)",
+        "reverseSniffing": "Sniffing ngược",
+        "workers": "Workers",
+        "reserved": "Đã đặt trước",
+        "minUploadInterval": "Khoảng upload tối thiểu (ms)",
+        "maxUploadSizeBytes": "Kích thước upload tối đa (byte)",
+        "uplinkChunkSize": "Kích thước chunk Uplink",
+        "noGrpcHeader": "Không có header gRPC",
+        "maxConcurrency": "Đồng thời tối đa",
+        "maxConnections": "Kết nối tối đa",
+        "maxReuseTimes": "Số lần tái sử dụng tối đa",
+        "maxRequestTimes": "Số yêu cầu tối đa",
+        "maxReusableSecs": "Số giây tái sử dụng tối đa",
+        "keepAlivePeriod": "Chu kỳ keep alive",
+        "authPassword": "Mật khẩu auth",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "tên máy chủ",
+        "verifyPeerName": "Xác minh tên peer",
+        "pinnedSha256": "SHA256 pinned",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "Khoảng keep alive",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "Giao diện",
+        "ipv6Only": "Chỉ IPv6",
+        "acceptProxyProtocol": "Chấp nhận proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "Thêm thư đi",
         "addOutbound": "Thêm thư đi",
         "addReverse": "Thêm đảo ngược",
         "addReverse": "Thêm đảo ngược",
@@ -840,14 +1213,14 @@
         "reverseTag": "Thẻ Ngược",
         "reverseTag": "Thẻ Ngược",
         "reverseTagDesc": "Thẻ outbound của proxy ngược đơn giản VLESS. Để trống để vô hiệu hóa.",
         "reverseTagDesc": "Thẻ outbound của proxy ngược đơn giản VLESS. Để trống để vô hiệu hóa.",
         "reverseTagPlaceholder": "thẻ outbound (để trống để vô hiệu hóa)",
         "reverseTagPlaceholder": "thẻ outbound (để trống để vô hiệu hóa)",
-        "tag": "Thẻ",
+        "tag": "Tag",
         "tagDesc": "thẻ duy nhất",
         "tagDesc": "thẻ duy nhất",
         "address": "Địa chỉ",
         "address": "Địa chỉ",
         "reverse": "Đảo ngược",
         "reverse": "Đảo ngược",
-        "domain": "Miền",
+        "domain": "Tên miền",
         "type": "Loại",
         "type": "Loại",
-        "bridge": "Cầu",
-        "portal": "Cổng thông tin",
+        "bridge": "Bridge",
+        "portal": "Portal",
         "link": "Liên kết",
         "link": "Liên kết",
         "intercon": "Kết nối",
         "intercon": "Kết nối",
         "settings": "cài đặt",
         "settings": "cài đặt",
@@ -860,6 +1233,8 @@
         "testSuccess": "Kiểm tra thành công",
         "testSuccess": "Kiểm tra thành công",
         "testFailed": "Kiểm tra thất bại",
         "testFailed": "Kiểm tra thất bại",
         "testError": "Không thể kiểm tra đầu ra",
         "testError": "Không thể kiểm tra đầu ra",
+        "testModeTooltip": "TCP: probe dial nhanh. HTTP: yêu cầu đầy đủ qua xray.",
+        "testAll": "Kiểm tra tất cả",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "Mã truy cập",
         "accessToken": "Mã truy cập",
         "country": "Quốc gia",
         "country": "Quốc gia",
@@ -874,8 +1249,18 @@
         "editBalancer": "Chỉnh sửa cân bằng",
         "editBalancer": "Chỉnh sửa cân bằng",
         "balancerStrategy": "Chiến lược",
         "balancerStrategy": "Chiến lược",
         "balancerSelectors": "Bộ chọn",
         "balancerSelectors": "Bộ chọn",
-        "tag": "Thẻ",
+        "tag": "Tag",
         "tagDesc": "thẻ duy nhất",
         "tagDesc": "thẻ duy nhất",
+        "tagDuplicate": "Tag đã được dùng bởi balancer khác",
+        "tagPlaceholder": "tag balancer duy nhất",
+        "selector": "Selector",
+        "fallback": "Fallback",
+        "expected": "Kỳ vọng",
+        "expectedPlaceholder": "số node tối ưu",
+        "maxRtt": "RTT tối đa",
+        "tolerance": "Dung sai",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "Không thể sử dụng balancerTag và outboundTag cùng một lúc. Nếu sử dụng cùng lúc thì chỉ outboundTag mới hoạt động."
         "balancerDesc": "Không thể sử dụng balancerTag và outboundTag cùng một lúc. Nếu sử dụng cùng lúc thì chỉ outboundTag mới hoạt động."
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "Mức Người Dùng",
         "userLevel": "Mức Người Dùng",
         "userLevelDesc": "Tất cả các kết nối được thực hiện thông qua inbound này sẽ sử dụng mức người dùng này. Giá trị mặc định là 0"
         "userLevelDesc": "Tất cả các kết nối được thực hiện thông qua inbound này sẽ sử dụng mức người dùng này. Giá trị mặc định là 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "Khóa riêng",
+        "noServers": "Không tìm thấy máy chủ cho quốc gia đã chọn",
+        "noPublicKey": "Máy chủ đã chọn không công bố khóa công khai NordLynx.",
+        "outboundAdded": "Đã thêm outbound NordVPN",
+        "outboundUpdated": "Đã cập nhật outbound NordVPN"
+      },
+      "warp": {
+        "licenseError": "Không thiết lập được giấy phép WARP.",
+        "fetchFirst": "Hãy lấy cấu hình WARP trước.",
+        "createAccount": "Tạo tài khoản WARP",
+        "accessToken": "Access token",
+        "deviceId": "ID thiết bị",
+        "licenseKey": "Khóa giấy phép",
+        "privateKey": "Khóa riêng",
+        "deleteAccount": "Xóa tài khoản",
+        "settings": "Cài đặt",
+        "licenseKeyLabel": "Khóa giấy phép WARP / WARP+",
+        "key": "Khóa",
+        "keyPlaceholder": "khóa WARP+ 26 ký tự",
+        "accountInfo": "Thông tin tài khoản",
+        "deviceName": "Tên thiết bị",
+        "deviceModel": "Kiểu thiết bị",
+        "deviceEnabled": "Thiết bị đã bật",
+        "accountType": "Loại tài khoản",
+        "role": "Vai trò",
+        "warpPlusData": "Dữ liệu WARP+",
+        "quota": "Hạn ngạch",
+        "usage": "Sử dụng",
+        "addOutbound": "Thêm outbound"
+      },
       "dns": {
       "dns": {
         "enable": "Kích hoạt DNS",
         "enable": "Kích hoạt DNS",
         "enableDesc": "Kích hoạt máy chủ DNS tích hợp",
         "enableDesc": "Kích hoạt máy chủ DNS tích hợp",
@@ -992,20 +1409,20 @@
       "2faFailed": "Lỗi 2FA",
       "2faFailed": "Lỗi 2FA",
       "report": "🕰 Báo cáo định kỳ: {{ .RunTime }}\r\n",
       "report": "🕰 Báo cáo định kỳ: {{ .RunTime }}\r\n",
       "datetime": "⏰ Ngày-Giờ: {{ .DateTime }}\r\n",
       "datetime": "⏰ Ngày-Giờ: {{ .DateTime }}\r\n",
-      "hostname": "💻 Tên máy chủ: {{ .Hostname }}\r\n",
+      "hostname": "💻 Host: {{ .Hostname }}\r\n",
       "version": "🚀 Phiên bản X-UI: {{ .Version }}\r\n",
       "version": "🚀 Phiên bản X-UI: {{ .Version }}\r\n",
       "xrayVersion": "📡 Phiên bản Xray: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Phiên bản Xray: {{ .XrayVersion }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
       "ip": "🌐 IP: {{ .IP }}\r\n",
-      "ips": "🔢 Các IP:\r\n{{ .IPs }}\r\n",
+      "ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
       "serverUpTime": "⏳ Thời gian hoạt động của máy chủ: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ Thời gian hoạt động của máy chủ: {{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 Tải máy chủ: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 Tải máy chủ: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 Bộ nhớ máy chủ: {{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 Số lượng kết nối TCP: {{ .Count }}\r\n",
-      "udpCount": "🔸 Số lượng kết nối UDP: {{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 Lưu lượng: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 Lưu lượng: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Trạng thái Xray: {{ .State }}\r\n",
+      "xrayStatus": "ℹ️ Trạng thái: {{ .State }}\r\n",
       "username": "👤 Tên người dùng: {{ .Username }}\r\n",
       "username": "👤 Tên người dùng: {{ .Username }}\r\n",
       "reason": "❗️ Lý do: {{ .Reason }}\r\n",
       "reason": "❗️ Lý do: {{ .Reason }}\r\n",
       "time": "⏰ Thời gian: {{ .Time }}\r\n",
       "time": "⏰ Thời gian: {{ .Time }}\r\n",
@@ -1020,7 +1437,7 @@
       "email": "📧 Email: {{ .Email }}\r\n",
       "email": "📧 Email: {{ .Email }}\r\n",
       "upload": "🔼 Tải lên: ↑{{ .Upload }}\r\n",
       "upload": "🔼 Tải lên: ↑{{ .Upload }}\r\n",
       "download": "🔽 Tải xuống: ↓{{ .Download }}\r\n",
       "download": "🔽 Tải xuống: ↓{{ .Download }}\r\n",
-      "total": "📊 Tổng cộng: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
+      "total": "📊 Tổng: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 Người dùng Telegram: {{ .TelegramID }}\r\n",
       "TGUser": "👤 Người dùng Telegram: {{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 Sự cạn kiệt {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 Sự cạn kiệt {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 Số lần cạn kiệt {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 Số lần cạn kiệt {{ .Type }}:\r\n",
@@ -1119,4 +1536,4 @@
       "chooseInbound": "Chọn một Inbound"
       "chooseInbound": "Chọn một Inbound"
     }
     }
   }
   }
-}
+}

+ 470 - 53
web/translation/zh-CN.json

@@ -8,15 +8,22 @@
   "save": "保存",
   "save": "保存",
   "logout": "登出",
   "logout": "登出",
   "create": "创建",
   "create": "创建",
+  "add": "添加",
+  "remove": "移除",
   "update": "更新",
   "update": "更新",
   "copy": "复制",
   "copy": "复制",
   "copied": "已复制",
   "copied": "已复制",
+  "more": "更多",
   "download": "下载",
   "download": "下载",
   "remark": "备注",
   "remark": "备注",
   "enable": "启用",
   "enable": "启用",
   "protocol": "协议",
   "protocol": "协议",
   "search": "搜索",
   "search": "搜索",
   "filter": "筛选",
   "filter": "筛选",
+  "all": "全部",
+  "from": "从",
+  "to": "到",
+  "done": "完成",
   "loading": "加载中...",
   "loading": "加载中...",
   "refresh": "刷新",
   "refresh": "刷新",
   "clear": "清除",
   "clear": "清除",
@@ -41,7 +48,7 @@
   "transmission": "传输",
   "transmission": "传输",
   "host": "主机",
   "host": "主机",
   "path": "路径",
   "path": "路径",
-  "camouflage": "伪装",
+  "camouflage": "混淆",
   "status": "状态",
   "status": "状态",
   "enabled": "开启",
   "enabled": "开启",
   "disabled": "关闭",
   "disabled": "关闭",
@@ -95,11 +102,12 @@
     "dark": "暗色",
     "dark": "暗色",
     "ultraDark": "超暗色",
     "ultraDark": "超暗色",
     "dashboard": "系统状态",
     "dashboard": "系统状态",
-    "inbounds": "入站列表",
+    "inbounds": "入站",
     "clients": "客户端",
     "clients": "客户端",
+    "groups": "分组",
     "nodes": "节点",
     "nodes": "节点",
     "settings": "面板设置",
     "settings": "面板设置",
-    "xray": "Xray 置",
+    "xray": "Xray 置",
     "apiDocs": "API 文档",
     "apiDocs": "API 文档",
     "logout": "退出登录",
     "logout": "退出登录",
     "link": "管理",
     "link": "管理",
@@ -123,9 +131,9 @@
       "cpu": "CPU",
       "cpu": "CPU",
       "logicalProcessors": "逻辑处理器",
       "logicalProcessors": "逻辑处理器",
       "frequency": "频率",
       "frequency": "频率",
-      "swap": "交换分区",
+      "swap": "Swap",
       "storage": "存储",
       "storage": "存储",
-      "memory": "内存",
+      "memory": "RAM",
       "threads": "线程",
       "threads": "线程",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
       "stopXray": "停止",
       "stopXray": "停止",
@@ -241,7 +249,7 @@
       "getConfigError": "检索配置文件时出错"
       "getConfigError": "检索配置文件时出错"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "入站列表",
+      "title": "入站",
       "totalDownUp": "总上传 / 下载",
       "totalDownUp": "总上传 / 下载",
       "totalUsage": "总用量",
       "totalUsage": "总用量",
       "inboundCount": "入站数量",
       "inboundCount": "入站数量",
@@ -252,7 +260,7 @@
       "deployTo": "部署到",
       "deployTo": "部署到",
       "localPanel": "本地面板",
       "localPanel": "本地面板",
       "fallbacks": {
       "fallbacks": {
-        "title": "回落",
+        "title": "Fallbacks",
         "help": "当此入站的连接未匹配任何客户端时,将其路由到另一个入站。在下方选择一个子入站,路由字段(SNI / ALPN / Path / xver)会从子入站的传输方式中自动填充——大多数场景无需再调整。每个子入站应监听 127.0.0.1,security=none。",
         "help": "当此入站的连接未匹配任何客户端时,将其路由到另一个入站。在下方选择一个子入站,路由字段(SNI / ALPN / Path / xver)会从子入站的传输方式中自动填充——大多数场景无需再调整。每个子入站应监听 127.0.0.1,security=none。",
         "empty": "暂无回落",
         "empty": "暂无回落",
         "add": "添加回落",
         "add": "添加回落",
@@ -273,7 +281,7 @@
       "portMap": "端口映射",
       "portMap": "端口映射",
       "traffic": "流量",
       "traffic": "流量",
       "details": "详细信息",
       "details": "详细信息",
-      "transportConfig": "传输配置",
+      "transportConfig": "传输",
       "expireDate": "到期时间",
       "expireDate": "到期时间",
       "createdAt": "创建时间",
       "createdAt": "创建时间",
       "updatedAt": "更新时间",
       "updatedAt": "更新时间",
@@ -292,6 +300,24 @@
       "delAllClients": "删除所有客户端",
       "delAllClients": "删除所有客户端",
       "delAllClientsConfirmTitle": "从 \"{remark}\" 中删除全部 {count} 个客户端?",
       "delAllClientsConfirmTitle": "从 \"{remark}\" 中删除全部 {count} 个客户端?",
       "delAllClientsConfirmContent": "从此入站中移除每个客户端并丢弃其流量记录。入站本身将保留。此操作无法撤销。",
       "delAllClientsConfirmContent": "从此入站中移除每个客户端并丢弃其流量记录。入站本身将保留。此操作无法撤销。",
+      "attachClients": "附加客户端到…",
+      "addClientsToGroup": "将客户端添加到分组…",
+      "attachClientsTitle": "从 “{remark}” 附加客户端",
+      "attachClientsDesc": "将相同的 {count} 个客户端(相同 UUID/密码和共享流量)附加到选定的入站。它们仍保留在此入站中。",
+      "attachClientsTargets": "目标入站",
+      "attachClientsNoTargets": "没有可附加的其他兼容入站。",
+      "attachClientsResult": "已附加 {attached},已跳过 {skipped}。",
+      "attachClientsResultMixed": "已附加 {attached},已跳过 {skipped},错误 {errors}。",
+      "attachClientsSelectLabel": "要附加的客户端",
+      "attachClientsSearchPlaceholder": "搜索邮箱或备注",
+      "attachClientsStatusDisabled": "已禁用",
+      "attachClientsSelectedCount": "已选 {selected}/{total}",
+      "detachClients": "分离客户端",
+      "detachClientsTitle": "从 “{remark}” 分离客户端",
+      "detachClientsDesc": "仅从此入站移除选中的客户端。客户端记录保留(使用 Delete 完全移除)。源共有 {count} 个客户端。",
+      "detachClientsResult": "已分离 {detached},已跳过 {skipped}。",
+      "detachClientsResultMixed": "已分离 {detached},已跳过 {skipped},错误 {errors}。",
+      "detachClientsSelectLabel": "要分离的客户端",
       "exportLinksTitle": "导出入站链接",
       "exportLinksTitle": "导出入站链接",
       "exportSubsTitle": "导出订阅链接",
       "exportSubsTitle": "导出订阅链接",
       "exportAllLinksTitle": "导出所有入站链接",
       "exportAllLinksTitle": "导出所有入站链接",
@@ -306,7 +332,7 @@
       "destinationPort": "目标端口",
       "destinationPort": "目标端口",
       "targetAddress": "目标地址",
       "targetAddress": "目标地址",
       "monitorDesc": "留空表示监听所有 IP",
       "monitorDesc": "留空表示监听所有 IP",
-      "meansNoLimit": "= 无限制(单位:GB)",
+      "meansNoLimit": "= 无限制。(单位: GB)",
       "totalFlow": "总流量",
       "totalFlow": "总流量",
       "leaveBlankToNeverExpire": "留空表示永不过期",
       "leaveBlankToNeverExpire": "留空表示永不过期",
       "noRecommendKeepDefault": "建议保留默认值",
       "noRecommendKeepDefault": "建议保留默认值",
@@ -333,7 +359,7 @@
       "delDepletedClients": "删除流量耗尽的客户端",
       "delDepletedClients": "删除流量耗尽的客户端",
       "delDepletedClientsTitle": "删除流量耗尽的客户端",
       "delDepletedClientsTitle": "删除流量耗尽的客户端",
       "delDepletedClientsContent": "确定要删除所有流量耗尽的客户端吗?",
       "delDepletedClientsContent": "确定要删除所有流量耗尽的客户端吗?",
-      "email": "电子邮件",
+      "email": "邮箱",
       "emailDesc": "电子邮件必须完全唯一",
       "emailDesc": "电子邮件必须完全唯一",
       "IPLimit": "IP 限制",
       "IPLimit": "IP 限制",
       "IPLimitDesc": "如果数量超过设置值,则禁用入站流量。(0 = 禁用)",
       "IPLimitDesc": "如果数量超过设置值,则禁用入站流量。(0 = 禁用)",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "IP 历史日志(要启用被禁用的入站流量,请清除日志)",
       "IPLimitlogDesc": "IP 历史日志(要启用被禁用的入站流量,请清除日志)",
       "IPLimitlogclear": "清除日志",
       "IPLimitlogclear": "清除日志",
       "setDefaultCert": "从面板设置证书",
       "setDefaultCert": "从面板设置证书",
-      "streamTab": "流",
+      "setDefaultCertEmpty": "面板尚未配置证书。请先在“设置”中设置。",
+      "streamTab": "Stream",
       "securityTab": "安全",
       "securityTab": "安全",
-      "sniffingTab": "嗅探",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "仅元数据",
       "sniffingMetadataOnly": "仅元数据",
       "sniffingRouteOnly": "仅路由",
       "sniffingRouteOnly": "仅路由",
       "sniffingIpsExcluded": "排除的 IP",
       "sniffingIpsExcluded": "排除的 IP",
@@ -361,15 +388,14 @@
         "allHelp": "在单个编辑器中编辑包含所有字段的完整入站对象。",
         "allHelp": "在单个编辑器中编辑包含所有字段的完整入站对象。",
         "settings": "设置",
         "settings": "设置",
         "settingsHelp": "Xray settings 块包装:",
         "settingsHelp": "Xray settings 块包装:",
-        "sniffing": "嗅探",
+        "sniffing": "Sniffing",
         "sniffingHelp": "Xray sniffing 块包装:",
         "sniffingHelp": "Xray sniffing 块包装:",
-        "stream": "",
+        "stream": "Stream",
         "streamHelp": "Xray stream 块包装:",
         "streamHelp": "Xray stream 块包装:",
         "jsonErrorPrefix": "高级 JSON"
         "jsonErrorPrefix": "高级 JSON"
       },
       },
       "telegramDesc": "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或({'@'}userinfobot",
       "telegramDesc": "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或({'@'}userinfobot",
       "subscriptionDesc": "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。",
       "subscriptionDesc": "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。",
-      "info": "信息",
       "same": "相同",
       "same": "相同",
       "inboundData": "入站数据",
       "inboundData": "入站数据",
       "exportInbound": "导出入站规则",
       "exportInbound": "导出入站规则",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "获取mldsa65证书时出错。",
         "getNewmldsa65Error": "获取mldsa65证书时出错。",
         "getNewVlessEncError": "获取VlessEnc证书时出错。"
         "getNewVlessEncError": "获取VlessEnc证书时出错。"
       },
       },
+      "form": {
+        "moveUp": "上移",
+        "moveDown": "下移",
+        "addAll": "全部添加",
+        "addAllFallbackTooltip": "为尚未连接的每个符合条件的入站添加一个 fallback 行",
+        "peers": "Peers",
+        "addPeer": "添加 peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "仅 Windows。CIDR 会自动添加到系统路由表,以便匹配的流量通过 TUN。",
+        "autoOutboundsInterface": "自动出站接口",
+        "autoOutboundsInterfaceTooltip": "出站流量的物理接口。使用 'auto' 进行检测;设置 Auto system routes 时自动启用。",
+        "rewriteAddress": "重写地址",
+        "rewritePort": "重写端口",
+        "allowedNetwork": "允许的网络",
+        "followRedirect": "跟随重定向",
+        "accounts": "账户",
+        "allowTransparent": "允许透明",
+        "encryptionMethod": "加密方法",
+        "visionTestseed": "Vision testseed",
+        "version": "版本",
+        "udpIdleTimeout": "UDP 空闲超时 (s)",
+        "masquerade": "伪装",
+        "type": "类型",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "重写 Host",
+        "skipTlsVerify": "跳过 TLS 验证",
+        "directory": "目录",
+        "statusCode": "状态码",
+        "body": "Body",
+        "headers": "请求头",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "请求版本",
+        "requestMethod": "请求方法",
+        "requestPath": "请求路径",
+        "requestHeaders": "请求头",
+        "responseVersion": "响应版本",
+        "responseStatus": "响应状态",
+        "responseReason": "响应原因",
+        "responseHeaders": "响应头",
+        "heartbeatPeriod": "心跳周期",
+        "serviceName": "服务名",
+        "authority": "Authority",
+        "multiMode": "多模式",
+        "maxBufferedUpload": "最大缓冲上传",
+        "maxUploadSize": "最大上传大小 (字节)",
+        "streamUpServer": "Stream-Up 服务器",
+        "serverMaxHeaderBytes": "服务器最大头字节",
+        "paddingBytes": "Padding 字节",
+        "uplinkHttpMethod": "Uplink HTTP 方法",
+        "paddingObfsMode": "Padding 混淆模式",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding 位置",
+        "paddingMethod": "Padding 方法",
+        "sessionPlacement": "Session 位置",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence 位置",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink 数据位置",
+        "uplinkDataKey": "Uplink 数据 Key",
+        "noSseHeader": "无 SSE 头",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "上行 (MB/s)",
+        "downlinkMbps": "下行 (MB/s)",
+        "cwndMultiplier": "CWND 倍数",
+        "maxSendingWindow": "最大发送窗口",
+        "externalProxy": "外部代理",
+        "sniPlaceholder": "SNI (默认为 host)",
+        "fingerprint": "指纹",
+        "defaultOption": "默认",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive 间隔",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "仅 V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "可信 X-Forwarded-For",
+        "addressPortStrategy": "地址+端口策略",
+        "tryDelayMs": "尝试延迟 (ms)",
+        "prioritizeIPv6": "IPv6 优先",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "最大并发尝试",
+        "customSockopt": "自定义 sockopt",
+        "addCustomOption": "添加自定义选项",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "自动",
+        "minMaxVersion": "最小/最大版本",
+        "rejectUnknownSni": "拒绝未知 SNI",
+        "disableSystemRoot": "禁用系统根",
+        "sessionResumption": "会话恢复",
+        "oneTimeLoading": "一次性加载",
+        "usageOption": "使用选项",
+        "buildChain": "构建证书链",
+        "echKey": "ECH key",
+        "echConfig": "ECH 配置",
+        "getNewEchCert": "获取新 ECH 证书",
+        "show": "显示",
+        "xver": "Xver",
+        "target": "目标",
+        "maxTimeDiff": "最大时间差 (ms)",
+        "minClientVer": "最小客户端版本",
+        "maxClientVer": "最大客户端版本",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "获取新证书",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "获取新 Seed"
+      },
+      "info": {
+        "mode": "模式",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "接口名称",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "出站接口",
+        "autoSystemRoutes": "自动系统路由",
+        "followRedirect": "FollowRedirect",
+        "auth": "认证",
+        "noKernelTun": "非内核 TUN",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Peer {n} 配置"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "请求",
           "request": "请求",
@@ -456,6 +615,20 @@
       "days": "天",
       "days": "天",
       "renew": "自动续期",
       "renew": "自动续期",
       "renewDesc": "到期后自动续期。(0 = 禁用) (单位: 天)",
       "renewDesc": "到期后自动续期。(0 = 禁用) (单位: 天)",
+      "searchPlaceholder": "搜索邮箱、备注、sub ID、UUID、密码、auth…",
+      "filterTitle": "筛选客户端",
+      "clearAllFilters": "清除全部",
+      "sortOldest": "最旧优先",
+      "sortNewest": "最新优先",
+      "sortRecentlyUpdated": "最近更新",
+      "sortRecentlyOnline": "最近在线",
+      "sortEmailAZ": "邮箱 A→Z",
+      "sortEmailZA": "邮箱 Z→A",
+      "sortMostTraffic": "流量最多",
+      "sortHighestRemaining": "剩余最多",
+      "sortExpiringSoonest": "即将过期",
+      "has": "拥有",
+      "hasNot": "不拥有",
       "title": "客户端",
       "title": "客户端",
       "actions": "操作",
       "actions": "操作",
       "totalGB": "总上传/下载 (GB)",
       "totalGB": "总上传/下载 (GB)",
@@ -466,6 +639,9 @@
       "subId": "订阅 ID",
       "subId": "订阅 ID",
       "online": "在线",
       "online": "在线",
       "email": "邮箱",
       "email": "邮箱",
+      "group": "分组",
+      "groupDesc": "用于对相关客户端进行分桶的逻辑标签(如团队、客户、地区)。可从工具栏筛选。",
+      "groupPlaceholder": "如 customer-a",
       "comment": "备注",
       "comment": "备注",
       "traffic": "流量",
       "traffic": "流量",
       "offline": "离线",
       "offline": "离线",
@@ -485,15 +661,49 @@
       "noLinks": "没有可共享的链接 — 请先将此客户端关联到支持协议的入站。",
       "noLinks": "没有可共享的链接 — 请先将此客户端关联到支持协议的入站。",
       "link": "链接",
       "link": "链接",
       "resetNotPossible": "请先将此客户端关联到入站。",
       "resetNotPossible": "请先将此客户端关联到入站。",
-      "general": "通用",
+      "general": "常规",
       "resetAllTraffics": "重置所有客户端流量",
       "resetAllTraffics": "重置所有客户端流量",
       "resetAllTrafficsTitle": "重置所有客户端流量?",
       "resetAllTrafficsTitle": "重置所有客户端流量?",
       "resetAllTrafficsContent": "所有客户端的上下行计数器将归零。配额与过期时间不受影响。该操作不可撤销。",
       "resetAllTrafficsContent": "所有客户端的上下行计数器将归零。配额与过期时间不受影响。该操作不可撤销。",
-      "empty": "尚无客户端 — 添加一个开始使用。",
       "deleteConfirmTitle": "删除客户端 {email}?",
       "deleteConfirmTitle": "删除客户端 {email}?",
       "deleteConfirmContent": "将从所有关联入站中移除该客户端并删除其流量记录。该操作不可撤销。",
       "deleteConfirmContent": "将从所有关联入站中移除该客户端并删除其流量记录。该操作不可撤销。",
       "deleteSelected": "删除 ({count})",
       "deleteSelected": "删除 ({count})",
       "adjustSelected": "调整 ({count})",
       "adjustSelected": "调整 ({count})",
+      "subLinksSelected": "订阅链接 ({count})",
+      "addToGroupTitle": "将 {count} 个客户端添加到分组",
+      "addToGroupTooltip": "选择现有分组或输入新名称。使用 Ungroup 操作从当前分组移除客户端。",
+      "addToGroupPlaceholder": "分组名称",
+      "addToGroupSuccessToast": "已将 {count} 个客户端添加到 {group}",
+      "ungroupSuccessToast": "已清除 {count} 个客户端的分组",
+      "ungroup": "取消分组",
+      "ungroupConfirmTitle": "将 {count} 个客户端从其分组中移除?",
+      "ungroupConfirmContent": "清除每个选中客户端的分组标签。客户端本身保留(使用 Delete 完全移除)。",
+      "addToGroup": "添加到分组",
+      "attach": "附加",
+      "adjust": "调整",
+      "subLinks": "订阅链接",
+      "selectedCount": "已选 {count} 项",
+      "attachSelected": "附加 ({count})",
+      "attachToInboundsTitle": "将 {count} 个客户端附加到入站",
+      "attachToInboundsDesc": "将选中的 {count} 个客户端(相同 UUID/密码和共享流量)附加到选定的入站。它们保留现有的附加关系。",
+      "attachToInboundsTargets": "目标入站",
+      "attachToInboundsNoTargets": "没有可用于附加的多用户入站。",
+      "detachSelected": "分离 ({count})",
+      "detach": "分离",
+      "detachFromInboundsTitle": "从入站分离 {count} 个客户端",
+      "detachFromInboundsDesc": "从选定的入站中移除选中的 {count} 个客户端。客户端未附加的配对将被静默跳过。客户端记录保留(使用 Delete 完全移除)。",
+      "detachFromInboundsTargets": "要分离的入站",
+      "detachFromInboundsNoTargets": "没有可用的多用户入站。",
+      "detachFromInboundsResult": "已分离 {detached},已跳过 {skipped}。",
+      "detachFromInboundsResultMixed": "已分离 {detached},已跳过 {skipped},错误 {errors}。",
+      "subLinksTitle": "订阅链接 ({count})",
+      "subLinkColumn": "订阅 URL",
+      "subJsonLinkColumn": "订阅 JSON URL",
+      "subLinksCopyAll": "全部复制",
+      "subLinksCopiedAll": "已复制 {count} 条链接",
+      "subLinksEmpty": "选中的客户端均无订阅 ID。",
+      "subLinksDisabled": "订阅服务已禁用。",
+      "subLinksDisabledHint": "在面板设置 → 订阅中启用订阅以生成链接。",
       "bulkDeleteConfirmTitle": "删除 {count} 个客户端?",
       "bulkDeleteConfirmTitle": "删除 {count} 个客户端?",
       "bulkDeleteConfirmContent": "每个所选客户端都会从关联的入站中被移除,其流量记录也会被删除。该操作不可撤销。",
       "bulkDeleteConfirmContent": "每个所选客户端都会从关联的入站中被移除,其流量记录也会被删除。该操作不可撤销。",
       "bulkAdjustTitle": "调整 {count} 个客户端",
       "bulkAdjustTitle": "调整 {count} 个客户端",
@@ -504,11 +714,12 @@
       "delDepleted": "删除已耗尽",
       "delDepleted": "删除已耗尽",
       "delDepletedConfirmTitle": "删除已耗尽的客户端?",
       "delDepletedConfirmTitle": "删除已耗尽的客户端?",
       "delDepletedConfirmContent": "删除所有流量配额已用尽或已过期的客户端。该操作不可撤销。",
       "delDepletedConfirmContent": "删除所有流量配额已用尽或已过期的客户端。该操作不可撤销。",
-      "auth": "Auth",
-      "hysteriaAuth": "Hysteria Auth",
+      "auth": "认证",
+      "hysteriaAuth": "Hysteria 认证",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "VMess 加密",
+      "reverseTag": "反向标签",
       "reverseTagPlaceholder": "可选 Reverse tag",
       "reverseTagPlaceholder": "可选 Reverse tag",
       "telegramId": "Telegram 用户 ID",
       "telegramId": "Telegram 用户 ID",
       "telegramIdPlaceholder": "数字形式的 Telegram 用户 ID (0 = 无)",
       "telegramIdPlaceholder": "数字形式的 Telegram 用户 ID (0 = 无)",
@@ -528,6 +739,44 @@
         "delDepleted": "已删除 {count} 个已耗尽的客户端"
         "delDepleted": "已删除 {count} 个已耗尽的客户端"
       }
       }
     },
     },
+    "groups": {
+      "title": "分组",
+      "name": "名称",
+      "clientCount": "分组中的客户端",
+      "totalGroups": "分组总数",
+      "totalGroupedClients": "有分组的客户端",
+      "emptyGroups": "空分组",
+      "addGroup": "添加分组",
+      "createSuccess": "已创建分组 “{name}”。",
+      "rename": "重命名",
+      "renameTitle": "重命名 {name}",
+      "renameCollision": "已存在名为 “{name}” 的分组。",
+      "renameSuccess": "已为 {count} 个客户端重命名分组。",
+      "deleteConfirmTitle": "删除分组 {name}?",
+      "deleteConfirmContent": "这将删除分组并清除 {count} 个客户端的标签。客户端本身不会被删除。",
+      "deleteSuccess": "已清除 {count} 个客户端的分组。",
+      "resetTraffic": "重置流量",
+      "resetConfirmTitle": "重置分组 {name} 的流量?",
+      "resetConfirmContent": "这将清零此分组中所有 {count} 个客户端的上行/下行流量。",
+      "resetSuccess": "已重置 {count} 个客户端的流量。",
+      "adjustSuccess": "已调整 {name} 中的 {count} 个客户端。",
+      "emptyForAction": "此分组尚无客户端。",
+      "deleteGroupOnly": "删除分组(保留客户端)",
+      "deleteClients": "删除分组中的客户端",
+      "deleteClientsConfirmTitle": "删除 {name} 中的所有客户端?",
+      "deleteClientsConfirmContent": "这将永久删除 {count} 个客户端及其流量记录。分组标签也会被清除。此操作无法撤销。",
+      "deleteClientsSuccess": "已删除 {count} 个客户端。",
+      "deleteClientsMixed": "已删除 {ok},已跳过 {failed}",
+      "addToGroup": "添加客户端…",
+      "addToGroupTitle": "添加客户端到分组 “{name}”",
+      "addToGroupDesc": "选择要添加到此分组的客户端。保留其现有入站附加;仅更改分组标签。已在此分组中的客户端不会列出。",
+      "addToGroupEmpty": "没有其他可添加的客户端。",
+      "addToGroupResult": "已将 {count} 个客户端添加到 {name}。",
+      "removeFromGroup": "移除客户端…",
+      "removeFromGroupTitle": "从分组 “{name}” 移除客户端",
+      "removeFromGroupDesc": "选择要从此分组中移除的成员。客户端本身保留(使用 “删除分组中的客户端” 完全移除)。",
+      "removeFromGroupResult": "已从 {name} 移除 {count} 个客户端。"
+    },
     "nodes": {
     "nodes": {
       "title": "节点",
       "title": "节点",
       "addNode": "添加节点",
       "addNode": "添加节点",
@@ -543,8 +792,8 @@
       "scheme": "协议",
       "scheme": "协议",
       "address": "地址",
       "address": "地址",
       "port": "端口",
       "port": "端口",
-      "basePath": "基础路径",
-      "apiToken": "API 令牌",
+      "basePath": "Base Path",
+      "apiToken": "API Token",
       "apiTokenPlaceholder": "远程面板设置页中的令牌",
       "apiTokenPlaceholder": "远程面板设置页中的令牌",
       "apiTokenHint": "远程面板在 设置 → API 令牌 中显示其 API 令牌。",
       "apiTokenHint": "远程面板在 设置 → API 令牌 中显示其 API 令牌。",
       "regenerate": "重新生成令牌",
       "regenerate": "重新生成令牌",
@@ -555,7 +804,7 @@
       "status": "状态",
       "status": "状态",
       "cpu": "CPU",
       "cpu": "CPU",
       "mem": "内存",
       "mem": "内存",
-      "uptime": "运行时",
+      "uptime": "运行时",
       "latency": "延迟",
       "latency": "延迟",
       "lastHeartbeat": "上次心跳",
       "lastHeartbeat": "上次心跳",
       "xrayVersion": "Xray 版本",
       "xrayVersion": "Xray 版本",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "默认根路径 \"/\" 众所周知 — 请更改为随机路径。",
       "warnDefaultBasePath": "默认根路径 \"/\" 众所周知 — 请更改为随机路径。",
       "warnDefaultSubPath": "默认订阅路径 \"/sub/\" 众所周知 — 请更改。",
       "warnDefaultSubPath": "默认订阅路径 \"/sub/\" 众所周知 — 请更改。",
       "warnDefaultJsonPath": "默认 JSON 订阅路径 \"/json/\" 众所周知 — 请更改。",
       "warnDefaultJsonPath": "默认 JSON 订阅路径 \"/json/\" 众所周知 — 请更改。",
-      "TGBotSettings": "Telegram 机器人配置",
+      "TGBotSettings": "Telegram 机器人",
       "panelListeningIP": "面板监听 IP",
       "panelListeningIP": "面板监听 IP",
       "panelListeningIPDesc": "默认留空监听所有 IP",
       "panelListeningIPDesc": "默认留空监听所有 IP",
       "panelListeningDomain": "面板监听域名",
       "panelListeningDomain": "面板监听域名",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "填写一个 '/' 开头的绝对路径",
       "publicKeyPathDesc": "填写一个 '/' 开头的绝对路径",
       "privateKeyPath": "面板证书密钥文件路径",
       "privateKeyPath": "面板证书密钥文件路径",
       "privateKeyPathDesc": "填写一个 '/' 开头的绝对路径",
       "privateKeyPathDesc": "填写一个 '/' 开头的绝对路径",
-      "panelUrlPath": "面板 url 根路径",
+      "panelUrlPath": "URI 路径",
       "panelUrlPathDesc": "必须以 '/' 开头,以 '/' 结尾",
       "panelUrlPathDesc": "必须以 '/' 开头,以 '/' 结尾",
       "pageSize": "分页大小",
       "pageSize": "分页大小",
       "pageSizeDesc": "定义入站表的页面大小。设置 0 表示禁用",
       "pageSizeDesc": "定义入站表的页面大小。设置 0 表示禁用",
+      "panelProxy": "面板网络代理",
+      "panelProxyDesc": "通过此代理路由面板自身的出站请求(geo 更新、Xray/面板版本检查、Telegram),以绕过服务端对 GitHub/Telegram 的过滤。接受 socks5:// 或 http(s)://,如本地 Xray SOCKS 入站。留空表示直连。",
       "remarkModel": "备注模型和分隔符",
       "remarkModel": "备注模型和分隔符",
       "datepicker": "日期选择器",
       "datepicker": "日期选择器",
       "datepickerPlaceholder": "选择日期",
       "datepickerPlaceholder": "选择日期",
@@ -630,11 +881,11 @@
       "newPassword": "新密码",
       "newPassword": "新密码",
       "telegramBotEnable": "启用 Telegram 机器人",
       "telegramBotEnable": "启用 Telegram 机器人",
       "telegramBotEnableDesc": "启用 Telegram 机器人功能",
       "telegramBotEnableDesc": "启用 Telegram 机器人功能",
-      "telegramToken": "Telegram 机器人令牌(token)",
+      "telegramToken": "Telegram Token",
       "telegramTokenDesc": "从 '{'@'}BotFather' 获取的 Telegram 机器人令牌",
       "telegramTokenDesc": "从 '{'@'}BotFather' 获取的 Telegram 机器人令牌",
-      "telegramProxy": "SOCKS5 Proxy",
+      "telegramProxy": "SOCKS 代理",
       "telegramProxyDesc": "启用 SOCKS5 代理连接到 Telegram(根据指南调整设置)",
       "telegramProxyDesc": "启用 SOCKS5 代理连接到 Telegram(根据指南调整设置)",
-      "telegramAPIServer": "Telegram API Server",
+      "telegramAPIServer": "Telegram API 服务器",
       "telegramAPIServerDesc": "要使用的 Telegram API 服务器。留空以使用默认服务器。",
       "telegramAPIServerDesc": "要使用的 Telegram API 服务器。留空以使用默认服务器。",
       "telegramChatId": "管理员聊天 ID",
       "telegramChatId": "管理员聊天 ID",
       "telegramChatIdDesc": "Telegram 管理员聊天 ID (多个以逗号分隔)(可通过 {'@'}userinfobot 获取,或在机器人中使用 '/id' 命令获取)",
       "telegramChatIdDesc": "Telegram 管理员聊天 ID (多个以逗号分隔)(可通过 {'@'}userinfobot 获取,或在机器人中使用 '/id' 命令获取)",
@@ -658,6 +909,8 @@
       "subEnable": "启用订阅服务",
       "subEnable": "启用订阅服务",
       "subEnableDesc": "启用订阅服务功能",
       "subEnableDesc": "启用订阅服务功能",
       "subJsonEnable": "单独启用/禁用 JSON 订阅端点。",
       "subJsonEnable": "单独启用/禁用 JSON 订阅端点。",
+      "subJsonEnableTitle": "JSON 订阅",
+      "subClashEnableTitle": "Clash / Mihomo 订阅",
       "subTitle": "订阅标题",
       "subTitle": "订阅标题",
       "subTitleDesc": "在VPN客户端中显示的标题",
       "subTitleDesc": "在VPN客户端中显示的标题",
       "subSupportUrl": "支持链接",
       "subSupportUrl": "支持链接",
@@ -693,7 +946,7 @@
       "subURI": "反向代理 URI",
       "subURI": "反向代理 URI",
       "subURIDesc": "用于代理后面的订阅 URL 的 URI 路径",
       "subURIDesc": "用于代理后面的订阅 URL 的 URI 路径",
       "externalTrafficInformEnable": "外部交通通知",
       "externalTrafficInformEnable": "外部交通通知",
-      "externalTrafficInformEnableDesc": "每次流量更新时通知外部 API",
+      "externalTrafficInformEnableDesc": "每次流量更新时通知外部 API",
       "externalTrafficInformURI": "外部流量通知 URI",
       "externalTrafficInformURI": "外部流量通知 URI",
       "externalTrafficInformURIDesc": "流量更新将发送到此 URI",
       "externalTrafficInformURIDesc": "流量更新将发送到此 URI",
       "restartXrayOnClientDisable": "客户端自动禁用后重启 Xray",
       "restartXrayOnClientDisable": "客户端自动禁用后重启 Xray",
@@ -703,7 +956,55 @@
       "fragmentSett": "设置",
       "fragmentSett": "设置",
       "noisesDesc": "启用 Noises.",
       "noisesDesc": "启用 Noises.",
       "noisesSett": "Noises 设置",
       "noisesSett": "Noises 设置",
-      "mux": "多路复用器",
+      "trustedProxyCidrs": "可信代理 CIDR",
+      "trustedProxyCidrsDesc": "允许设置转发 host、proto 和客户端 IP 标头的 IP/CIDR(逗号分隔)。",
+      "ldap": {
+        "enable": "启用 LDAP 同步",
+        "host": "LDAP host",
+        "port": "LDAP 端口",
+        "useTls": "使用 TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "已配置;留空以保留当前密码。",
+        "passwordUnconfigured": "未配置。",
+        "passwordPlaceholder": "已配置 - 输入新值以替换",
+        "baseDn": "Base DN",
+        "userFilter": "用户筛选",
+        "userAttr": "用户属性 (username/email)",
+        "vlessField": "VLESS flag 属性",
+        "flagField": "通用 flag 属性 (可选)",
+        "flagFieldDesc": "如设置,将覆盖 VLESS flag — 如 shadowInactive。",
+        "truthyValues": "Truthy 值",
+        "truthyValuesDesc": "逗号分隔;默认: true,1,yes,on",
+        "invertFlag": "反转 flag",
+        "invertFlagDesc": "当属性表示已禁用时启用 (如 shadowInactive)。",
+        "syncSchedule": "同步计划",
+        "syncScheduleDesc": "类 cron 字符串,如 @every 1m",
+        "inboundTags": "入站标签",
+        "inboundTagsDesc": "允许 LDAP 同步自动创建或删除客户端的入站。",
+        "noInbounds": "未找到入站。请先在“入站”中创建。",
+        "autoCreate": "自动创建客户端",
+        "autoDelete": "自动删除客户端",
+        "defaultTotalGb": "默认总流量 (GB)",
+        "defaultExpiryDays": "默认到期 (天)",
+        "defaultIpLimit": "默认 IP 限制"
+      },
+      "subFormats": {
+        "packets": "数据包",
+        "length": "长度",
+        "interval": "间隔",
+        "maxSplit": "最大分割",
+        "noises": "噪声",
+        "noiseItem": "噪声 №{n}",
+        "type": "类型",
+        "packet": "数据包",
+        "delayMs": "延迟 (ms)",
+        "applyTo": "应用于",
+        "addNoise": "+ 噪声",
+        "concurrency": "并发",
+        "xudpConcurrency": "xudp 并发",
+        "xudpUdp443": "xudp UDP 443"
+      },
+      "mux": "Mux",
       "muxDesc": "在已建立的数据流内传输多个独立的数据流",
       "muxDesc": "在已建立的数据流内传输多个独立的数据流",
       "muxSett": "复用器设置",
       "muxSett": "复用器设置",
       "direct": "直接连接",
       "direct": "直接连接",
@@ -756,8 +1057,11 @@
     "xray": {
     "xray": {
       "title": "Xray 配置",
       "title": "Xray 配置",
       "save": "保存",
       "save": "保存",
-      "restart": "重 Xray",
+      "restart": "重启 Xray",
       "restartSuccess": "Xray 已成功重新启动",
       "restartSuccess": "Xray 已成功重新启动",
+      "restartOutputTitle": "Xray 重启输出",
+      "restartConfirmTitle": "重启 xray?",
+      "restartConfirmContent": "使用已保存的配置重新加载 xray 服务。",
       "stopSuccess": "Xray 已成功停止",
       "stopSuccess": "Xray 已成功停止",
       "restartError": "重启Xray时发生错误。",
       "restartError": "重启Xray时发生错误。",
       "stopError": "停止Xray时发生错误。",
       "stopError": "停止Xray时发生错误。",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "出站测试 URL",
       "outboundTestUrl": "出站测试 URL",
       "outboundTestUrlDesc": "测试出站连接时使用的 URL",
       "outboundTestUrlDesc": "测试出站连接时使用的 URL",
       "Torrent": "屏蔽 BitTorrent 协议",
       "Torrent": "屏蔽 BitTorrent 协议",
-      "Inbounds": "入站规则",
+      "Inbounds": "入站",
       "InboundsDesc": "接受来自特定客户端的流量",
       "InboundsDesc": "接受来自特定客户端的流量",
-      "Outbounds": "出站规则",
+      "Outbounds": "出站",
       "Balancers": "负载均衡",
       "Balancers": "负载均衡",
+      "balancerTagRequired": "标签为必填项",
+      "balancerSelectorRequired": "至少选择一个出站",
       "OutboundsDesc": "设置出站流量传出方式",
       "OutboundsDesc": "设置出站流量传出方式",
       "Routings": "路由规则",
       "Routings": "路由规则",
       "RoutingsDesc": "每条规则的优先级都很重要",
       "RoutingsDesc": "每条规则的优先级都很重要",
@@ -832,6 +1138,73 @@
         "edit": "编辑规则",
         "edit": "编辑规则",
         "useComma": "逗号分隔的项目"
         "useComma": "逗号分隔的项目"
       },
       },
+      "routing": {
+        "dragToReorder": "拖动以重新排序"
+      },
+      "ruleForm": {
+        "sourceIps": "源 IP",
+        "sourcePort": "源端口",
+        "vlessRoute": "VLESS 路由",
+        "attributes": "属性",
+        "value": "值",
+        "user": "用户",
+        "inboundTags": "入站标签",
+        "outboundTag": "出站标签",
+        "balancerTag": "均衡器标签",
+        "balancerTagTooltip": "通过其中一个已配置的负载均衡器路由流量"
+      },
+      "outboundForm": {
+        "tagDuplicate": "该标签已被其他出站使用",
+        "tagRequired": "标签为必填项",
+        "tagPlaceholder": "唯一标签",
+        "localIpPlaceholder": "本地 IP",
+        "addressRequired": "地址为必填项",
+        "portRequired": "端口为必填项",
+        "optional": "可选",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "UoT 版本",
+        "inboundTag": "入站标签",
+        "inboundTagPlaceholder": "用于路由规则的入站标签",
+        "responseType": "响应类型",
+        "rewriteNetwork": "重写网络",
+        "unchanged": "(未更改)",
+        "unchangedAddress": "(未更改) 如 1.1.1.1",
+        "rules": "规则",
+        "ruleN": "规则 {n}",
+        "action": "操作",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "最终规则",
+        "overrideXrayPrivateIp": "覆盖 Xray 默认的私有 IP 阻止",
+        "blockDelay": "阻塞延迟 (ms)",
+        "reverseSniffing": "反向 sniffing",
+        "workers": "Workers",
+        "reserved": "保留",
+        "minUploadInterval": "最小上传间隔 (ms)",
+        "maxUploadSizeBytes": "最大上传大小 (字节)",
+        "uplinkChunkSize": "Uplink chunk 大小",
+        "noGrpcHeader": "无 gRPC 头",
+        "maxConcurrency": "最大并发",
+        "maxConnections": "最大连接",
+        "maxReuseTimes": "最大复用次数",
+        "maxRequestTimes": "最大请求次数",
+        "maxReusableSecs": "最大可复用秒数",
+        "keepAlivePeriod": "keep alive 周期",
+        "authPassword": "认证密码",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "服务器名",
+        "verifyPeerName": "验证 peer 名称",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "keep alive 间隔",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "接口",
+        "ipv6Only": "仅 IPv6",
+        "acceptProxyProtocol": "接受 proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "添加出站",
         "addOutbound": "添加出站",
         "addReverse": "添加反向",
         "addReverse": "添加反向",
@@ -860,6 +1233,8 @@
         "testSuccess": "测试成功",
         "testSuccess": "测试成功",
         "testFailed": "测试失败",
         "testFailed": "测试失败",
         "testError": "测试出站失败",
         "testError": "测试出站失败",
+        "testModeTooltip": "TCP: 快速 dial-only 探测。HTTP: 通过 xray 的完整请求。",
+        "testAll": "全部测试",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "访问令牌",
         "accessToken": "访问令牌",
         "country": "国家",
         "country": "国家",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "选择器",
         "balancerSelectors": "选择器",
         "tag": "标签",
         "tag": "标签",
         "tagDesc": "唯一标签",
         "tagDesc": "唯一标签",
+        "tagDuplicate": "该标签已被其他均衡器使用",
+        "tagPlaceholder": "唯一均衡器标签",
+        "selector": "选择器",
+        "fallback": "Fallback",
+        "expected": "期望",
+        "expectedPlaceholder": "最佳节点数",
+        "maxRtt": "最大 RTT",
+        "tolerance": "容差",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "无法同时使用 balancerTag 和 outboundTag。如果同时使用,则只有 outboundTag 会生效。"
         "balancerDesc": "无法同时使用 balancerTag 和 outboundTag。如果同时使用,则只有 outboundTag 会生效。"
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "用户级别",
         "userLevel": "用户级别",
         "userLevelDesc": "通过此入站的所有连接都将使用此用户级别。默认值为 0"
         "userLevelDesc": "通过此入站的所有连接都将使用此用户级别。默认值为 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "私钥",
+        "noServers": "未找到选定国家/地区的服务器",
+        "noPublicKey": "选定的服务器未公布 NordLynx 公钥。",
+        "outboundAdded": "NordVPN 出站已添加",
+        "outboundUpdated": "NordVPN 出站已更新"
+      },
+      "warp": {
+        "licenseError": "设置 WARP 许可证失败。",
+        "fetchFirst": "请先获取 WARP 配置。",
+        "createAccount": "创建 WARP 账户",
+        "accessToken": "Access token",
+        "deviceId": "设备 ID",
+        "licenseKey": "许可证密钥",
+        "privateKey": "私钥",
+        "deleteAccount": "删除账户",
+        "settings": "设置",
+        "licenseKeyLabel": "WARP / WARP+ 许可证密钥",
+        "key": "密钥",
+        "keyPlaceholder": "26 位 WARP+ 密钥",
+        "accountInfo": "账户信息",
+        "deviceName": "设备名称",
+        "deviceModel": "设备型号",
+        "deviceEnabled": "设备已启用",
+        "accountType": "账户类型",
+        "role": "角色",
+        "warpPlusData": "WARP+ 数据",
+        "quota": "配额",
+        "usage": "使用",
+        "addOutbound": "添加出站"
+      },
       "dns": {
       "dns": {
         "enable": "启用 DNS",
         "enable": "启用 DNS",
         "enableDesc": "启用内置 DNS 服务器",
         "enableDesc": "启用内置 DNS 服务器",
@@ -911,7 +1328,7 @@
         "strategyDesc": "解析域名的总体策略",
         "strategyDesc": "解析域名的总体策略",
         "add": "添加服务器",
         "add": "添加服务器",
         "edit": "编辑服务器",
         "edit": "编辑服务器",
-        "domains": "域",
+        "domains": "域",
         "expectIPs": "预期 IP",
         "expectIPs": "预期 IP",
         "unexpectIPs": "意外IP",
         "unexpectIPs": "意外IP",
         "useSystemHosts": "使用系统Hosts",
         "useSystemHosts": "使用系统Hosts",
@@ -992,35 +1409,35 @@
       "2faFailed": "2FA 失败",
       "2faFailed": "2FA 失败",
       "report": "🕰 定时报告:{{ .RunTime }}\r\n",
       "report": "🕰 定时报告:{{ .RunTime }}\r\n",
       "datetime": "⏰ 日期时间:{{ .DateTime }}\r\n",
       "datetime": "⏰ 日期时间:{{ .DateTime }}\r\n",
-      "hostname": "💻 主机名:{{ .Hostname }}\r\n",
+      "hostname": "💻 主机: {{ .Hostname }}\r\n",
       "version": "🚀 X-UI 版本:{{ .Version }}\r\n",
       "version": "🚀 X-UI 版本:{{ .Version }}\r\n",
       "xrayVersion": "📡 Xray 版本: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Xray 版本: {{ .XrayVersion }}\r\n",
-      "ipv6": "🌐 IPv6{{ .IPv6 }}\r\n",
-      "ipv4": "🌐 IPv4{{ .IPv4 }}\r\n",
-      "ip": "🌐 IP{{ .IP }}\r\n",
-      "ips": "🔢 IP 地址:\r\n{{ .IPs }}\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": "⏳ 服务器运行时间:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ 服务器运行时间:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 服务器负载:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 服务器负载:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 服务器内存:{{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 TCP 连接数:{{ .Count }}\r\n",
-      "udpCount": "🔸 UDP 连接数:{{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Xray 状态:{{ .State }}\r\n",
+      "xrayStatus": "ℹ️ 状态: {{ .State }}\r\n",
       "username": "👤 用户名:{{ .Username }}\r\n",
       "username": "👤 用户名:{{ .Username }}\r\n",
       "reason": "❗️ 原因:{{ .Reason }}\r\n",
       "reason": "❗️ 原因:{{ .Reason }}\r\n",
       "time": "⏰ 时间:{{ .Time }}\r\n",
       "time": "⏰ 时间:{{ .Time }}\r\n",
-      "inbound": "📍 入站{{ .Remark }}\r\n",
-      "port": "🔌 端口{{ .Port }}\r\n",
+      "inbound": "📍 入站: {{ .Remark }}\r\n",
+      "port": "🔌 端口: {{ .Port }}\r\n",
       "expire": "📅 过期日期:{{ .Time }}\r\n",
       "expire": "📅 过期日期:{{ .Time }}\r\n",
       "expireIn": "📅 剩余时间:{{ .Time }}\r\n",
       "expireIn": "📅 剩余时间:{{ .Time }}\r\n",
       "active": "💡 激活:{{ .Enable }}\r\n",
       "active": "💡 激活:{{ .Enable }}\r\n",
       "enabled": "🚨 已启用:{{ .Enable }}\r\n",
       "enabled": "🚨 已启用:{{ .Enable }}\r\n",
       "online": "🌐 连接状态:{{ .Status }}\r\n",
       "online": "🌐 连接状态:{{ .Status }}\r\n",
       "lastOnline": "🔙 上次在线: {{ .Time }}\r\n",
       "lastOnline": "🔙 上次在线: {{ .Time }}\r\n",
-      "email": "📧 邮箱{{ .Email }}\r\n",
-      "upload": "🔼 上传↑{{ .Upload }}\r\n",
-      "download": "🔽 下载↓{{ .Download }}\r\n",
-      "total": "📊 总计{{ .UpDown }} / {{ .Total }}\r\n",
+      "email": "📧 邮箱: {{ .Email }}\r\n",
+      "upload": "🔼 上传: ↑{{ .Upload }}\r\n",
+      "download": "🔽 下载: ↓{{ .Download }}\r\n",
+      "total": "📊 总计: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 电报用户:{{ .TelegramID }}\r\n",
       "TGUser": "👤 电报用户:{{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 耗尽的 {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 耗尽的 {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 耗尽的 {{ .Type }} 数量:\r\n",
       "exhaustedCount": "🚨 耗尽的 {{ .Type }} 数量:\r\n",
@@ -1030,7 +1447,7 @@
       "backupTime": "🗄 备份时间:{{ .Time }}\r\n",
       "backupTime": "🗄 备份时间:{{ .Time }}\r\n",
       "refreshedOn": "\r\n📋🔄 刷新时间:{{ .Time }}\r\n\r\n",
       "refreshedOn": "\r\n📋🔄 刷新时间:{{ .Time }}\r\n\r\n",
       "yes": "✅ 是的",
       "yes": "✅ 是的",
-      "no": "❌ 没有",
+      "no": "❌ ",
       "received_id": "🔑📥 ID 已更新。",
       "received_id": "🔑📥 ID 已更新。",
       "received_password": "🔑📥 密码已更新。",
       "received_password": "🔑📥 密码已更新。",
       "received_email": "📧📥 邮箱已更新。",
       "received_email": "📧📥 邮箱已更新。",
@@ -1077,7 +1494,7 @@
       "ipLimit": "🔢 IP 限制",
       "ipLimit": "🔢 IP 限制",
       "setTGUser": "👤 设置 Telegram 用户",
       "setTGUser": "👤 设置 Telegram 用户",
       "toggle": "🔘 启用/禁用",
       "toggle": "🔘 启用/禁用",
-      "custom": "🔢 风俗",
+      "custom": "🔢 自定义",
       "confirmNumber": "✅ 确认: {{ .Num }}",
       "confirmNumber": "✅ 确认: {{ .Num }}",
       "confirmNumberAdd": "✅ 确认添加:{{ .Num }}",
       "confirmNumberAdd": "✅ 确认添加:{{ .Num }}",
       "limitTraffic": "🚧 流量限制",
       "limitTraffic": "🚧 流量限制",
@@ -1091,7 +1508,7 @@
       "change_password": "⚙️🔑 密码",
       "change_password": "⚙️🔑 密码",
       "change_email": "⚙️📧 邮箱",
       "change_email": "⚙️📧 邮箱",
       "change_comment": "⚙️💬 评论",
       "change_comment": "⚙️💬 评论",
-      "change_flow": "⚙️🚦 流控",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "重置所有流量",
       "ResetAllTraffics": "重置所有流量",
       "SortedTrafficUsageReport": "排序的流量使用报告"
       "SortedTrafficUsageReport": "排序的流量使用报告"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "选择一个入站"
       "chooseInbound": "选择一个入站"
     }
     }
   }
   }
-}
+}

+ 481 - 64
web/translation/zh-TW.json

@@ -8,15 +8,22 @@
   "save": "儲存",
   "save": "儲存",
   "logout": "登出",
   "logout": "登出",
   "create": "建立",
   "create": "建立",
+  "add": "新增",
+  "remove": "移除",
   "update": "更新",
   "update": "更新",
   "copy": "複製",
   "copy": "複製",
   "copied": "已複製",
   "copied": "已複製",
+  "more": "更多",
   "download": "下載",
   "download": "下載",
   "remark": "備註",
   "remark": "備註",
   "enable": "啟用",
   "enable": "啟用",
   "protocol": "協議",
   "protocol": "協議",
   "search": "搜尋",
   "search": "搜尋",
   "filter": "篩選",
   "filter": "篩選",
+  "all": "全部",
+  "from": "從",
+  "to": "到",
+  "done": "完成",
   "loading": "載入中...",
   "loading": "載入中...",
   "refresh": "重新整理",
   "refresh": "重新整理",
   "clear": "清除",
   "clear": "清除",
@@ -41,14 +48,14 @@
   "transmission": "傳輸",
   "transmission": "傳輸",
   "host": "主機",
   "host": "主機",
   "path": "路徑",
   "path": "路徑",
-  "camouflage": "偽裝",
+  "camouflage": "混淆",
   "status": "狀態",
   "status": "狀態",
   "enabled": "開啟",
   "enabled": "開啟",
   "disabled": "關閉",
   "disabled": "關閉",
   "depleted": "耗盡",
   "depleted": "耗盡",
   "depletingSoon": "即將耗盡",
   "depletingSoon": "即將耗盡",
   "offline": "離線",
   "offline": "離線",
-  "online": "上",
+  "online": "上",
   "domainName": "域名",
   "domainName": "域名",
   "monitor": "監聽",
   "monitor": "監聽",
   "certificate": "憑證",
   "certificate": "憑證",
@@ -95,8 +102,9 @@
     "dark": "深色",
     "dark": "深色",
     "ultraDark": "超深色",
     "ultraDark": "超深色",
     "dashboard": "系統狀態",
     "dashboard": "系統狀態",
-    "inbounds": "入站列表",
+    "inbounds": "入站",
     "clients": "客戶端",
     "clients": "客戶端",
+    "groups": "群組",
     "nodes": "節點",
     "nodes": "節點",
     "settings": "面板設定",
     "settings": "面板設定",
     "xray": "Xray 設定",
     "xray": "Xray 設定",
@@ -123,13 +131,13 @@
       "cpu": "CPU",
       "cpu": "CPU",
       "logicalProcessors": "邏輯處理器",
       "logicalProcessors": "邏輯處理器",
       "frequency": "頻率",
       "frequency": "頻率",
-      "swap": "交換空間",
+      "swap": "Swap",
       "storage": "儲存",
       "storage": "儲存",
-      "memory": "記憶體",
+      "memory": "RAM",
       "threads": "執行緒",
       "threads": "執行緒",
       "xrayStatus": "Xray",
       "xrayStatus": "Xray",
       "stopXray": "停止",
       "stopXray": "停止",
-      "restartXray": "重啟",
+      "restartXray": "重",
       "xraySwitch": "版本",
       "xraySwitch": "版本",
       "xrayUpdates": "Xray 更新",
       "xrayUpdates": "Xray 更新",
       "xraySwitchClick": "選擇你要切換到的版本",
       "xraySwitchClick": "選擇你要切換到的版本",
@@ -226,9 +234,9 @@
       "customGeoErrUpdateAllIncomplete": "有一個或多個自訂 geo 來源更新失敗",
       "customGeoErrUpdateAllIncomplete": "有一個或多個自訂 geo 來源更新失敗",
       "customGeoEmpty": "尚無自訂 geo 來源 — 點擊「新增」以建立",
       "customGeoEmpty": "尚無自訂 geo 來源 — 點擊「新增」以建立",
       "dontRefresh": "安裝中,請勿重新整理此頁面",
       "dontRefresh": "安裝中,請勿重新整理此頁面",
-      "logs": "日誌",
+      "logs": "記錄",
       "config": "配置",
       "config": "配置",
-      "backup": "備份和恢復",
+      "backup": "備份",
       "backupTitle": "備份和恢復",
       "backupTitle": "備份和恢復",
       "exportDatabase": "備份",
       "exportDatabase": "備份",
       "exportDatabaseDesc": "點擊下載包含當前資料庫備份的 .db 文件到您的設備。",
       "exportDatabaseDesc": "點擊下載包含當前資料庫備份的 .db 文件到您的設備。",
@@ -241,7 +249,7 @@
       "getConfigError": "檢索設定檔時發生錯誤"
       "getConfigError": "檢索設定檔時發生錯誤"
     },
     },
     "inbounds": {
     "inbounds": {
-      "title": "入站列表",
+      "title": "入站",
       "totalDownUp": "總上傳 / 下載",
       "totalDownUp": "總上傳 / 下載",
       "totalUsage": "總用量",
       "totalUsage": "總用量",
       "inboundCount": "入站數量",
       "inboundCount": "入站數量",
@@ -252,7 +260,7 @@
       "deployTo": "部署到",
       "deployTo": "部署到",
       "localPanel": "本機面板",
       "localPanel": "本機面板",
       "fallbacks": {
       "fallbacks": {
-        "title": "回落",
+        "title": "Fallbacks",
         "help": "當此入站的連線未匹配任何用戶時,將其路由到另一個入站。在下方選擇一個子入站,路由欄位(SNI / ALPN / Path / xver)會自動從子入站的傳輸方式填入——大多數情境不需要再調整。每個子入站應監聽 127.0.0.1,security=none。",
         "help": "當此入站的連線未匹配任何用戶時,將其路由到另一個入站。在下方選擇一個子入站,路由欄位(SNI / ALPN / Path / xver)會自動從子入站的傳輸方式填入——大多數情境不需要再調整。每個子入站應監聽 127.0.0.1,security=none。",
         "empty": "尚未新增回落",
         "empty": "尚未新增回落",
         "add": "新增回落",
         "add": "新增回落",
@@ -269,11 +277,11 @@
         "defaultCatchAll": "預設 — 兜底匹配其餘"
         "defaultCatchAll": "預設 — 兜底匹配其餘"
       },
       },
       "protocol": "協議",
       "protocol": "協議",
-      "port": "埠",
-      "portMap": "埠映射",
+      "port": "連接埠",
+      "portMap": "連接埠對應",
       "traffic": "流量",
       "traffic": "流量",
       "details": "詳細資訊",
       "details": "詳細資訊",
-      "transportConfig": "傳輸配置",
+      "transportConfig": "傳輸",
       "expireDate": "到期時間",
       "expireDate": "到期時間",
       "createdAt": "建立時間",
       "createdAt": "建立時間",
       "updatedAt": "更新時間",
       "updatedAt": "更新時間",
@@ -292,6 +300,24 @@
       "delAllClients": "刪除所有客戶端",
       "delAllClients": "刪除所有客戶端",
       "delAllClientsConfirmTitle": "從「{remark}」中刪除全部 {count} 個客戶端?",
       "delAllClientsConfirmTitle": "從「{remark}」中刪除全部 {count} 個客戶端?",
       "delAllClientsConfirmContent": "從此入站中移除每個客戶端並捨棄其流量記錄。入站本身將保留。此操作無法復原。",
       "delAllClientsConfirmContent": "從此入站中移除每個客戶端並捨棄其流量記錄。入站本身將保留。此操作無法復原。",
+      "attachClients": "附加客戶端到…",
+      "addClientsToGroup": "將客戶端加入群組…",
+      "attachClientsTitle": "從「{remark}」附加客戶端",
+      "attachClientsDesc": "將相同的 {count} 個客戶端(相同 UUID/密碼與共享流量)附加到選定入站。它們仍保留於此入站。",
+      "attachClientsTargets": "目標入站",
+      "attachClientsNoTargets": "沒有可附加的其他相容入站。",
+      "attachClientsResult": "已附加 {attached},已略過 {skipped}。",
+      "attachClientsResultMixed": "已附加 {attached},已略過 {skipped},錯誤 {errors}。",
+      "attachClientsSelectLabel": "要附加的客戶端",
+      "attachClientsSearchPlaceholder": "搜尋電子郵件或備註",
+      "attachClientsStatusDisabled": "已停用",
+      "attachClientsSelectedCount": "已選 {selected}/{total}",
+      "detachClients": "分離客戶端",
+      "detachClientsTitle": "從「{remark}」分離客戶端",
+      "detachClientsDesc": "僅從此入站移除選取的客戶端。客戶端記錄保留(用 Delete 完全移除)。來源共有 {count} 個客戶端。",
+      "detachClientsResult": "已分離 {detached},已略過 {skipped}。",
+      "detachClientsResultMixed": "已分離 {detached},已略過 {skipped},錯誤 {errors}。",
+      "detachClientsSelectLabel": "要分離的客戶端",
       "exportLinksTitle": "匯出入站連結",
       "exportLinksTitle": "匯出入站連結",
       "exportSubsTitle": "匯出訂閱連結",
       "exportSubsTitle": "匯出訂閱連結",
       "exportAllLinksTitle": "匯出所有入站連結",
       "exportAllLinksTitle": "匯出所有入站連結",
@@ -306,7 +332,7 @@
       "destinationPort": "目標埠",
       "destinationPort": "目標埠",
       "targetAddress": "目標地址",
       "targetAddress": "目標地址",
       "monitorDesc": "留空表示監聽所有 IP",
       "monitorDesc": "留空表示監聽所有 IP",
-      "meansNoLimit": "= 無限制(單位:GB)",
+      "meansNoLimit": "= 無限制。(單位: GB)",
       "totalFlow": "總流量",
       "totalFlow": "總流量",
       "leaveBlankToNeverExpire": "留空表示永不過期",
       "leaveBlankToNeverExpire": "留空表示永不過期",
       "noRecommendKeepDefault": "建議保留預設值",
       "noRecommendKeepDefault": "建議保留預設值",
@@ -341,9 +367,10 @@
       "IPLimitlogDesc": "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)",
       "IPLimitlogDesc": "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)",
       "IPLimitlogclear": "清除日誌",
       "IPLimitlogclear": "清除日誌",
       "setDefaultCert": "從面板設定證書",
       "setDefaultCert": "從面板設定證書",
-      "streamTab": "串流",
+      "setDefaultCertEmpty": "面板尚未設定憑證。請先在「設定」中設定。",
+      "streamTab": "Stream",
       "securityTab": "安全",
       "securityTab": "安全",
-      "sniffingTab": "嗅探",
+      "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "僅中繼資料",
       "sniffingMetadataOnly": "僅中繼資料",
       "sniffingRouteOnly": "僅路由",
       "sniffingRouteOnly": "僅路由",
       "sniffingIpsExcluded": "排除的 IP",
       "sniffingIpsExcluded": "排除的 IP",
@@ -361,15 +388,14 @@
         "allHelp": "在單一編輯器中編輯包含所有欄位的完整入站物件。",
         "allHelp": "在單一編輯器中編輯包含所有欄位的完整入站物件。",
         "settings": "設定",
         "settings": "設定",
         "settingsHelp": "Xray settings 區塊包裝:",
         "settingsHelp": "Xray settings 區塊包裝:",
-        "sniffing": "嗅探",
+        "sniffing": "Sniffing",
         "sniffingHelp": "Xray sniffing 區塊包裝:",
         "sniffingHelp": "Xray sniffing 區塊包裝:",
-        "stream": "串流",
+        "stream": "Stream",
         "streamHelp": "Xray stream 區塊包裝:",
         "streamHelp": "Xray stream 區塊包裝:",
         "jsonErrorPrefix": "進階 JSON"
         "jsonErrorPrefix": "進階 JSON"
       },
       },
       "telegramDesc": "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或({'@'}userinfobot",
       "telegramDesc": "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或({'@'}userinfobot",
       "subscriptionDesc": "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。",
       "subscriptionDesc": "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。",
-      "info": "資訊",
       "same": "相同",
       "same": "相同",
       "inboundData": "入站資料",
       "inboundData": "入站資料",
       "exportInbound": "匯出入站規則",
       "exportInbound": "匯出入站規則",
@@ -406,6 +432,139 @@
         "getNewmldsa65Error": "取得mldsa65憑證時發生錯誤。",
         "getNewmldsa65Error": "取得mldsa65憑證時發生錯誤。",
         "getNewVlessEncError": "取得VlessEnc憑證時發生錯誤。"
         "getNewVlessEncError": "取得VlessEnc憑證時發生錯誤。"
       },
       },
+      "form": {
+        "moveUp": "上移",
+        "moveDown": "下移",
+        "addAll": "全部新增",
+        "addAllFallbackTooltip": "為每個尚未連線的符合條件入站新增一個 fallback 列",
+        "peers": "Peers",
+        "addPeer": "新增 peer",
+        "keepAlive": "Keep-alive",
+        "autoSystemRoutesTooltip": "僅 Windows。CIDR 會自動加入系統路由表,使匹配的流量通過 TUN。",
+        "autoOutboundsInterface": "自動出站介面",
+        "autoOutboundsInterfaceTooltip": "出站流量的實體介面。使用 'auto' 進行偵測;設定 Auto system routes 時自動啟用。",
+        "rewriteAddress": "改寫地址",
+        "rewritePort": "改寫連接埠",
+        "allowedNetwork": "允許的網路",
+        "followRedirect": "跟隨重新導向",
+        "accounts": "帳號",
+        "allowTransparent": "允許透明",
+        "encryptionMethod": "加密方法",
+        "visionTestseed": "Vision testseed",
+        "version": "版本",
+        "udpIdleTimeout": "UDP 閒置逾時 (s)",
+        "masquerade": "偽裝",
+        "type": "類型",
+        "upstreamUrl": "Upstream URL",
+        "rewriteHost": "改寫 Host",
+        "skipTlsVerify": "略過 TLS 驗證",
+        "directory": "目錄",
+        "statusCode": "狀態碼",
+        "body": "Body",
+        "headers": "標頭",
+        "proxyProtocol": "Proxy Protocol",
+        "requestVersion": "請求版本",
+        "requestMethod": "請求方法",
+        "requestPath": "請求路徑",
+        "requestHeaders": "請求標頭",
+        "responseVersion": "回應版本",
+        "responseStatus": "回應狀態",
+        "responseReason": "回應原因",
+        "responseHeaders": "回應標頭",
+        "heartbeatPeriod": "心跳週期",
+        "serviceName": "服務名稱",
+        "authority": "Authority",
+        "multiMode": "多模式",
+        "maxBufferedUpload": "最大緩衝上傳",
+        "maxUploadSize": "最大上傳大小 (位元組)",
+        "streamUpServer": "Stream-Up 伺服器",
+        "serverMaxHeaderBytes": "伺服器最大標頭位元組",
+        "paddingBytes": "Padding 位元組",
+        "uplinkHttpMethod": "Uplink HTTP 方法",
+        "paddingObfsMode": "Padding 混淆模式",
+        "paddingKey": "Padding Key",
+        "paddingHeader": "Padding Header",
+        "paddingPlacement": "Padding 位置",
+        "paddingMethod": "Padding 方法",
+        "sessionPlacement": "Session 位置",
+        "sessionKey": "Session Key",
+        "sequencePlacement": "Sequence 位置",
+        "sequenceKey": "Sequence Key",
+        "uplinkDataPlacement": "Uplink 資料位置",
+        "uplinkDataKey": "Uplink 資料 Key",
+        "noSseHeader": "無 SSE 標頭",
+        "ttiMs": "TTI (ms)",
+        "uplinkMbps": "上行 (MB/s)",
+        "downlinkMbps": "下行 (MB/s)",
+        "cwndMultiplier": "CWND 倍數",
+        "maxSendingWindow": "最大發送視窗",
+        "externalProxy": "外部代理",
+        "sniPlaceholder": "SNI (預設為 host)",
+        "fingerprint": "指紋",
+        "defaultOption": "預設",
+        "routeMark": "Route Mark",
+        "tcpKeepAliveInterval": "TCP Keep Alive 間隔",
+        "tcpKeepAliveIdle": "TCP Keep Alive Idle",
+        "tcpMaxSeg": "TCP Max Seg",
+        "tcpUserTimeout": "TCP User Timeout",
+        "tcpWindowClamp": "TCP Window Clamp",
+        "tcpFastOpen": "TCP Fast Open",
+        "multipathTcp": "Multipath TCP",
+        "penetrate": "Penetrate",
+        "v6Only": "僅 V6",
+        "tcpCongestion": "TCP Congestion",
+        "dialerProxy": "Dialer Proxy",
+        "trustedXForwardedFor": "信任的 X-Forwarded-For",
+        "addressPortStrategy": "地址+連接埠策略",
+        "tryDelayMs": "嘗試延遲 (ms)",
+        "prioritizeIPv6": "IPv6 優先",
+        "interleave": "Interleave",
+        "maxConcurrentTry": "最大並發嘗試",
+        "customSockopt": "自訂 sockopt",
+        "addCustomOption": "新增自訂選項",
+        "serverNameIndication": "SNI",
+        "cipherSuites": "Cipher Suites",
+        "autoOption": "自動",
+        "minMaxVersion": "最小/最大版本",
+        "rejectUnknownSni": "拒絕未知 SNI",
+        "disableSystemRoot": "停用系統根",
+        "sessionResumption": "工作階段恢復",
+        "oneTimeLoading": "一次性載入",
+        "usageOption": "使用選項",
+        "buildChain": "建立憑證鏈",
+        "echKey": "ECH key",
+        "echConfig": "ECH 設定",
+        "getNewEchCert": "取得新 ECH 憑證",
+        "show": "顯示",
+        "xver": "Xver",
+        "target": "目標",
+        "maxTimeDiff": "最大時間差 (ms)",
+        "minClientVer": "最小客戶端版本",
+        "maxClientVer": "最大客戶端版本",
+        "shortIds": "Short IDs",
+        "spiderX": "SpiderX",
+        "getNewCert": "取得新憑證",
+        "mldsa65Seed": "mldsa65 Seed",
+        "mldsa65Verify": "mldsa65 Verify",
+        "getNewSeed": "取得新 Seed"
+      },
+      "info": {
+        "mode": "模式",
+        "grpcServiceName": "grpc serviceName",
+        "grpcMultiMode": "grpc multiMode",
+        "interfaceName": "介面名稱",
+        "mtu": "MTU",
+        "gateway": "Gateway",
+        "dns": "DNS",
+        "outboundsInterface": "出站介面",
+        "autoSystemRoutes": "自動系統路由",
+        "followRedirect": "FollowRedirect",
+        "auth": "認證",
+        "noKernelTun": "非核心 TUN",
+        "keepAlive": "Keep alive",
+        "peerNumber": "Peer {n}",
+        "peerNumberConfig": "Peer {n} 設定"
+      },
       "stream": {
       "stream": {
         "general": {
         "general": {
           "request": "請求",
           "request": "請求",
@@ -456,6 +615,20 @@
       "days": "天",
       "days": "天",
       "renew": "自動續期",
       "renew": "自動續期",
       "renewDesc": "到期後自動續期。(0 = 停用) (單位: 天)",
       "renewDesc": "到期後自動續期。(0 = 停用) (單位: 天)",
+      "searchPlaceholder": "搜尋電子郵件、備註、sub ID、UUID、密碼、auth…",
+      "filterTitle": "篩選客戶端",
+      "clearAllFilters": "清除全部",
+      "sortOldest": "最舊優先",
+      "sortNewest": "最新優先",
+      "sortRecentlyUpdated": "最近更新",
+      "sortRecentlyOnline": "最近上線",
+      "sortEmailAZ": "電子郵件 A→Z",
+      "sortEmailZA": "電子郵件 Z→A",
+      "sortMostTraffic": "流量最多",
+      "sortHighestRemaining": "剩餘最多",
+      "sortExpiringSoonest": "即將到期",
+      "has": "擁有",
+      "hasNot": "不擁有",
       "title": "客戶端",
       "title": "客戶端",
       "actions": "操作",
       "actions": "操作",
       "totalGB": "總上傳/下載 (GB)",
       "totalGB": "總上傳/下載 (GB)",
@@ -465,7 +638,10 @@
       "password": "密碼",
       "password": "密碼",
       "subId": "訂閱 ID",
       "subId": "訂閱 ID",
       "online": "上線",
       "online": "上線",
-      "email": "信箱",
+      "email": "電子郵件",
+      "group": "群組",
+      "groupDesc": "用於將相關客戶端歸類的邏輯標籤(如團隊、客戶、地區)。可從工具列篩選。",
+      "groupPlaceholder": "如 customer-a",
       "comment": "備註",
       "comment": "備註",
       "traffic": "流量",
       "traffic": "流量",
       "offline": "離線",
       "offline": "離線",
@@ -485,15 +661,49 @@
       "noLinks": "沒有可共享的連結 — 請先將此客戶端關聯至支援協定的入站。",
       "noLinks": "沒有可共享的連結 — 請先將此客戶端關聯至支援協定的入站。",
       "link": "連結",
       "link": "連結",
       "resetNotPossible": "請先將此客戶端關聯至入站。",
       "resetNotPossible": "請先將此客戶端關聯至入站。",
-      "general": "通用",
+      "general": "一般",
       "resetAllTraffics": "重設所有客戶端流量",
       "resetAllTraffics": "重設所有客戶端流量",
       "resetAllTrafficsTitle": "重設所有客戶端流量?",
       "resetAllTrafficsTitle": "重設所有客戶端流量?",
       "resetAllTrafficsContent": "所有客戶端的上下行計數器將歸零。配額與到期時間不受影響。此操作無法復原。",
       "resetAllTrafficsContent": "所有客戶端的上下行計數器將歸零。配額與到期時間不受影響。此操作無法復原。",
-      "empty": "尚無客戶端 — 新增一個開始使用。",
       "deleteConfirmTitle": "刪除客戶端 {email}?",
       "deleteConfirmTitle": "刪除客戶端 {email}?",
       "deleteConfirmContent": "將從所有關聯入站中移除該客戶端並刪除其流量紀錄。此操作無法復原。",
       "deleteConfirmContent": "將從所有關聯入站中移除該客戶端並刪除其流量紀錄。此操作無法復原。",
       "deleteSelected": "刪除 ({count})",
       "deleteSelected": "刪除 ({count})",
       "adjustSelected": "調整 ({count})",
       "adjustSelected": "調整 ({count})",
+      "subLinksSelected": "訂閱連結 ({count})",
+      "addToGroupTitle": "將 {count} 個客戶端加入群組",
+      "addToGroupTooltip": "選擇現有群組或輸入新名稱。使用 Ungroup 操作從當前群組移除客戶端。",
+      "addToGroupPlaceholder": "群組名稱",
+      "addToGroupSuccessToast": "已將 {count} 個客戶端加入 {group}",
+      "ungroupSuccessToast": "已清除 {count} 個客戶端的群組",
+      "ungroup": "取消群組",
+      "ungroupConfirmTitle": "將 {count} 個客戶端從其群組中移除?",
+      "ungroupConfirmContent": "清除每個選取客戶端的群組標籤。客戶端本身保留(用 Delete 完全移除)。",
+      "addToGroup": "加入群組",
+      "attach": "附加",
+      "adjust": "調整",
+      "subLinks": "訂閱連結",
+      "selectedCount": "已選 {count} 項",
+      "attachSelected": "附加 ({count})",
+      "attachToInboundsTitle": "將 {count} 個客戶端附加到入站",
+      "attachToInboundsDesc": "將選取的 {count} 個客戶端(相同 UUID/密碼與共享流量)附加到選定入站。它們保留現有附加關係。",
+      "attachToInboundsTargets": "目標入站",
+      "attachToInboundsNoTargets": "沒有可供附加的多用戶入站。",
+      "detachSelected": "分離 ({count})",
+      "detach": "分離",
+      "detachFromInboundsTitle": "從入站分離 {count} 個客戶端",
+      "detachFromInboundsDesc": "從選定入站中移除選取的 {count} 個客戶端。客戶端未附加的配對會被靜默略過。客戶端記錄保留(用 Delete 完全移除)。",
+      "detachFromInboundsTargets": "要分離的入站",
+      "detachFromInboundsNoTargets": "沒有可用的多用戶入站。",
+      "detachFromInboundsResult": "已分離 {detached},已略過 {skipped}。",
+      "detachFromInboundsResultMixed": "已分離 {detached},已略過 {skipped},錯誤 {errors}。",
+      "subLinksTitle": "訂閱連結 ({count})",
+      "subLinkColumn": "訂閱 URL",
+      "subJsonLinkColumn": "訂閱 JSON URL",
+      "subLinksCopyAll": "全部複製",
+      "subLinksCopiedAll": "已複製 {count} 條連結",
+      "subLinksEmpty": "選取的客戶端皆無訂閱 ID。",
+      "subLinksDisabled": "訂閱服務已停用。",
+      "subLinksDisabledHint": "在面板設定 → 訂閱中啟用訂閱以產生連結。",
       "bulkDeleteConfirmTitle": "刪除 {count} 個客戶端?",
       "bulkDeleteConfirmTitle": "刪除 {count} 個客戶端?",
       "bulkDeleteConfirmContent": "每個所選客戶端都會從關聯的入站中被移除,其流量紀錄也會被刪除。此操作無法復原。",
       "bulkDeleteConfirmContent": "每個所選客戶端都會從關聯的入站中被移除,其流量紀錄也會被刪除。此操作無法復原。",
       "bulkAdjustTitle": "調整 {count} 個客戶端",
       "bulkAdjustTitle": "調整 {count} 個客戶端",
@@ -504,11 +714,12 @@
       "delDepleted": "刪除已耗盡",
       "delDepleted": "刪除已耗盡",
       "delDepletedConfirmTitle": "刪除已耗盡的客戶端?",
       "delDepletedConfirmTitle": "刪除已耗盡的客戶端?",
       "delDepletedConfirmContent": "刪除所有流量配額已用盡或已過期的客戶端。此操作無法復原。",
       "delDepletedConfirmContent": "刪除所有流量配額已用盡或已過期的客戶端。此操作無法復原。",
-      "auth": "Auth",
-      "hysteriaAuth": "Hysteria Auth",
+      "auth": "認證",
+      "hysteriaAuth": "Hysteria 認證",
       "uuid": "UUID",
       "uuid": "UUID",
       "flow": "Flow",
       "flow": "Flow",
-      "reverseTag": "Reverse tag",
+      "vmessSecurity": "VMess 加密",
+      "reverseTag": "反向標籤",
       "reverseTagPlaceholder": "選用 Reverse tag",
       "reverseTagPlaceholder": "選用 Reverse tag",
       "telegramId": "Telegram 使用者 ID",
       "telegramId": "Telegram 使用者 ID",
       "telegramIdPlaceholder": "數字形式的 Telegram 使用者 ID (0 = 無)",
       "telegramIdPlaceholder": "數字形式的 Telegram 使用者 ID (0 = 無)",
@@ -528,12 +739,50 @@
         "delDepleted": "已刪除 {count} 個已耗盡的客戶端"
         "delDepleted": "已刪除 {count} 個已耗盡的客戶端"
       }
       }
     },
     },
+    "groups": {
+      "title": "群組",
+      "name": "名稱",
+      "clientCount": "群組中的客戶端",
+      "totalGroups": "群組總數",
+      "totalGroupedClients": "有群組的客戶端",
+      "emptyGroups": "空群組",
+      "addGroup": "新增群組",
+      "createSuccess": "已建立群組「{name}」。",
+      "rename": "重新命名",
+      "renameTitle": "重新命名 {name}",
+      "renameCollision": "已存在名為「{name}」的群組。",
+      "renameSuccess": "已為 {count} 個客戶端重新命名群組。",
+      "deleteConfirmTitle": "刪除群組 {name}?",
+      "deleteConfirmContent": "這將刪除群組並清除 {count} 個客戶端的標籤。客戶端本身不會被刪除。",
+      "deleteSuccess": "已清除 {count} 個客戶端的群組。",
+      "resetTraffic": "重置流量",
+      "resetConfirmTitle": "重置群組 {name} 的流量?",
+      "resetConfirmContent": "這將將此群組中所有 {count} 個客戶端的上行/下行流量歸零。",
+      "resetSuccess": "已重置 {count} 個客戶端的流量。",
+      "adjustSuccess": "已調整 {name} 中的 {count} 個客戶端。",
+      "emptyForAction": "此群組尚無客戶端。",
+      "deleteGroupOnly": "刪除群組(保留客戶端)",
+      "deleteClients": "刪除群組中的客戶端",
+      "deleteClientsConfirmTitle": "刪除 {name} 中的所有客戶端?",
+      "deleteClientsConfirmContent": "這將永久刪除 {count} 個客戶端及其流量記錄。群組標籤亦會被清除。此操作無法復原。",
+      "deleteClientsSuccess": "已刪除 {count} 個客戶端。",
+      "deleteClientsMixed": "已刪除 {ok},已略過 {failed}",
+      "addToGroup": "新增客戶端…",
+      "addToGroupTitle": "將客戶端加入群組「{name}」",
+      "addToGroupDesc": "選擇要加入此群組的客戶端。保留其現有入站附加;僅更改群組標籤。已在此群組中的客戶端不會列出。",
+      "addToGroupEmpty": "沒有其他可加入的客戶端。",
+      "addToGroupResult": "已將 {count} 個客戶端加入 {name}。",
+      "removeFromGroup": "移除客戶端…",
+      "removeFromGroupTitle": "從群組「{name}」移除客戶端",
+      "removeFromGroupDesc": "選擇要從此群組移除的成員。客戶端本身保留(用「刪除群組中的客戶端」完全移除)。",
+      "removeFromGroupResult": "已從 {name} 移除 {count} 個客戶端。"
+    },
     "nodes": {
     "nodes": {
       "title": "節點",
       "title": "節點",
       "addNode": "新增節點",
       "addNode": "新增節點",
       "editNode": "編輯節點",
       "editNode": "編輯節點",
       "totalNodes": "節點總數",
       "totalNodes": "節點總數",
-      "onlineNodes": "線上",
+      "onlineNodes": "上",
       "offlineNodes": "離線",
       "offlineNodes": "離線",
       "avgLatency": "平均延遲",
       "avgLatency": "平均延遲",
       "name": "名稱",
       "name": "名稱",
@@ -542,9 +791,9 @@
       "remark": "備註",
       "remark": "備註",
       "scheme": "協議",
       "scheme": "協議",
       "address": "位址",
       "address": "位址",
-      "port": "埠",
-      "basePath": "基礎路徑",
-      "apiToken": "API 權杖",
+      "port": "連接埠",
+      "basePath": "Base Path",
+      "apiToken": "API Token",
       "apiTokenPlaceholder": "遠端面板設定頁中的權杖",
       "apiTokenPlaceholder": "遠端面板設定頁中的權杖",
       "apiTokenHint": "遠端面板在 設定 → API 權杖 中顯示其 API 權杖。",
       "apiTokenHint": "遠端面板在 設定 → API 權杖 中顯示其 API 權杖。",
       "regenerate": "重新產生權杖",
       "regenerate": "重新產生權杖",
@@ -555,7 +804,7 @@
       "status": "狀態",
       "status": "狀態",
       "cpu": "CPU",
       "cpu": "CPU",
       "mem": "記憶體",
       "mem": "記憶體",
-      "uptime": "行時間",
+      "uptime": "行時間",
       "latency": "延遲",
       "latency": "延遲",
       "lastHeartbeat": "上次心跳",
       "lastHeartbeat": "上次心跳",
       "xrayVersion": "Xray 版本",
       "xrayVersion": "Xray 版本",
@@ -570,7 +819,7 @@
       "deleteConfirmTitle": "刪除節點「{name}」?",
       "deleteConfirmTitle": "刪除節點「{name}」?",
       "deleteConfirmContent": "這將停止監控該節點。遠端面板本身不受影響。",
       "deleteConfirmContent": "這將停止監控該節點。遠端面板本身不受影響。",
       "statusValues": {
       "statusValues": {
-        "online": "上",
+        "online": "上",
         "offline": "離線",
         "offline": "離線",
         "unknown": "未知"
         "unknown": "未知"
       },
       },
@@ -590,7 +839,7 @@
       "title": "面板設定",
       "title": "面板設定",
       "save": "儲存",
       "save": "儲存",
       "infoDesc": "此處的所有更改都需要儲存並重啟面板才能生效",
       "infoDesc": "此處的所有更改都需要儲存並重啟面板才能生效",
-      "restartPanel": "重啟面板",
+      "restartPanel": "重面板",
       "restartPanelDesc": "確定要重啟面板嗎?若重啟後無法訪問面板,請前往伺服器檢視面板日誌資訊",
       "restartPanelDesc": "確定要重啟面板嗎?若重啟後無法訪問面板,請前往伺服器檢視面板日誌資訊",
       "restartPanelSuccess": "面板已成功重新啟動",
       "restartPanelSuccess": "面板已成功重新啟動",
       "actions": "操作",
       "actions": "操作",
@@ -604,7 +853,7 @@
       "warnDefaultBasePath": "預設根路徑 \"/\" 廣為人知 — 請更改為隨機路徑。",
       "warnDefaultBasePath": "預設根路徑 \"/\" 廣為人知 — 請更改為隨機路徑。",
       "warnDefaultSubPath": "預設訂閱路徑 \"/sub/\" 廣為人知 — 請更改。",
       "warnDefaultSubPath": "預設訂閱路徑 \"/sub/\" 廣為人知 — 請更改。",
       "warnDefaultJsonPath": "預設 JSON 訂閱路徑 \"/json/\" 廣為人知 — 請更改。",
       "warnDefaultJsonPath": "預設 JSON 訂閱路徑 \"/json/\" 廣為人知 — 請更改。",
-      "TGBotSettings": "Telegram 機器人配置",
+      "TGBotSettings": "Telegram 機器人",
       "panelListeningIP": "面板監聽 IP",
       "panelListeningIP": "面板監聽 IP",
       "panelListeningIPDesc": "預設留空監聽所有 IP",
       "panelListeningIPDesc": "預設留空監聽所有 IP",
       "panelListeningDomain": "面板監聽域名",
       "panelListeningDomain": "面板監聽域名",
@@ -615,10 +864,12 @@
       "publicKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
       "publicKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
       "privateKeyPath": "面板證書金鑰檔案路徑",
       "privateKeyPath": "面板證書金鑰檔案路徑",
       "privateKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
       "privateKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
-      "panelUrlPath": "面板 url 根路徑",
+      "panelUrlPath": "URI 路徑",
       "panelUrlPathDesc": "必須以 '/' 開頭,以 '/' 結尾",
       "panelUrlPathDesc": "必須以 '/' 開頭,以 '/' 結尾",
       "pageSize": "分頁大小",
       "pageSize": "分頁大小",
       "pageSizeDesc": "定義入站表的頁面大小。設定 0 表示禁用",
       "pageSizeDesc": "定義入站表的頁面大小。設定 0 表示禁用",
+      "panelProxy": "面板網路代理",
+      "panelProxyDesc": "透過此代理路由面板自身的出站請求(geo 更新、Xray/面板版本檢查、Telegram),以繞過伺服器端對 GitHub/Telegram 的過濾。接受 socks5:// 或 http(s)://,如本地 Xray SOCKS 入站。留空表示直連。",
       "remarkModel": "備註模型和分隔符",
       "remarkModel": "備註模型和分隔符",
       "datepicker": "日期選擇器",
       "datepicker": "日期選擇器",
       "datepickerPlaceholder": "選擇日期",
       "datepickerPlaceholder": "選擇日期",
@@ -630,11 +881,11 @@
       "newPassword": "新密碼",
       "newPassword": "新密碼",
       "telegramBotEnable": "啟用 Telegram 機器人",
       "telegramBotEnable": "啟用 Telegram 機器人",
       "telegramBotEnableDesc": "啟用 Telegram 機器人功能",
       "telegramBotEnableDesc": "啟用 Telegram 機器人功能",
-      "telegramToken": "Telegram 機器人令牌(token)",
+      "telegramToken": "Telegram Token",
       "telegramTokenDesc": "從 '{'@'}BotFather' 獲取的 Telegram 機器人令牌",
       "telegramTokenDesc": "從 '{'@'}BotFather' 獲取的 Telegram 機器人令牌",
-      "telegramProxy": "SOCKS5 Proxy",
+      "telegramProxy": "SOCKS 代理",
       "telegramProxyDesc": "啟用 SOCKS5 代理連線到 Telegram(根據指南調整設定)",
       "telegramProxyDesc": "啟用 SOCKS5 代理連線到 Telegram(根據指南調整設定)",
-      "telegramAPIServer": "Telegram API Server",
+      "telegramAPIServer": "Telegram API 伺服器",
       "telegramAPIServerDesc": "要使用的 Telegram API 伺服器。留空以使用預設伺服器。",
       "telegramAPIServerDesc": "要使用的 Telegram API 伺服器。留空以使用預設伺服器。",
       "telegramChatId": "管理員聊天 ID",
       "telegramChatId": "管理員聊天 ID",
       "telegramChatIdDesc": "Telegram 管理員聊天 ID (多個以逗號分隔)(可通過 {'@'}userinfobot 獲取,或在機器人中使用 '/id' 命令獲取)",
       "telegramChatIdDesc": "Telegram 管理員聊天 ID (多個以逗號分隔)(可通過 {'@'}userinfobot 獲取,或在機器人中使用 '/id' 命令獲取)",
@@ -658,6 +909,8 @@
       "subEnable": "啟用訂閱服務",
       "subEnable": "啟用訂閱服務",
       "subEnableDesc": "啟用訂閱服務功能",
       "subEnableDesc": "啟用訂閱服務功能",
       "subJsonEnable": "獨立啟用/停用 JSON 訂閱端點。",
       "subJsonEnable": "獨立啟用/停用 JSON 訂閱端點。",
+      "subJsonEnableTitle": "JSON 訂閱",
+      "subClashEnableTitle": "Clash / Mihomo 訂閱",
       "subTitle": "訂閱標題",
       "subTitle": "訂閱標題",
       "subTitleDesc": "在VPN客戶端中顯示的標題",
       "subTitleDesc": "在VPN客戶端中顯示的標題",
       "subSupportUrl": "支援連結",
       "subSupportUrl": "支援連結",
@@ -693,7 +946,7 @@
       "subURI": "反向代理 URI",
       "subURI": "反向代理 URI",
       "subURIDesc": "用於代理後面的訂閱 URL 的 URI 路徑",
       "subURIDesc": "用於代理後面的訂閱 URL 的 URI 路徑",
       "externalTrafficInformEnable": "外部交通通知",
       "externalTrafficInformEnable": "外部交通通知",
-      "externalTrafficInformEnableDesc": "每次流量更新時通知外部 API",
+      "externalTrafficInformEnableDesc": "每次流量更新時通知外部 API",
       "externalTrafficInformURI": "外部流量通知 URI",
       "externalTrafficInformURI": "外部流量通知 URI",
       "externalTrafficInformURIDesc": "流量更新將會傳送到此 URI",
       "externalTrafficInformURIDesc": "流量更新將會傳送到此 URI",
       "restartXrayOnClientDisable": "用戶自動停用後重新啟動 Xray",
       "restartXrayOnClientDisable": "用戶自動停用後重新啟動 Xray",
@@ -703,7 +956,55 @@
       "fragmentSett": "設定",
       "fragmentSett": "設定",
       "noisesDesc": "啟用 Noises.",
       "noisesDesc": "啟用 Noises.",
       "noisesSett": "Noises 設定",
       "noisesSett": "Noises 設定",
-      "mux": "多路複用器",
+      "trustedProxyCidrs": "信任代理 CIDR",
+      "trustedProxyCidrsDesc": "允許設定轉發 host、proto 與客戶端 IP 標頭的 IP/CIDR(逗號分隔)。",
+      "ldap": {
+        "enable": "啟用 LDAP 同步",
+        "host": "LDAP host",
+        "port": "LDAP 連接埠",
+        "useTls": "使用 TLS (LDAPS)",
+        "bindDn": "Bind DN",
+        "passwordConfigured": "已設定;留空以保留目前密碼。",
+        "passwordUnconfigured": "未設定。",
+        "passwordPlaceholder": "已設定 - 輸入新值以取代",
+        "baseDn": "Base DN",
+        "userFilter": "使用者篩選",
+        "userAttr": "使用者屬性 (username/email)",
+        "vlessField": "VLESS flag 屬性",
+        "flagField": "通用 flag 屬性 (選用)",
+        "flagFieldDesc": "若設定,將覆寫 VLESS flag — 如 shadowInactive。",
+        "truthyValues": "Truthy 值",
+        "truthyValuesDesc": "以逗號分隔;預設: true,1,yes,on",
+        "invertFlag": "反轉 flag",
+        "invertFlagDesc": "當屬性表示已停用時啟用 (如 shadowInactive)。",
+        "syncSchedule": "同步排程",
+        "syncScheduleDesc": "類 cron 字串,如 @every 1m",
+        "inboundTags": "入站標籤",
+        "inboundTagsDesc": "允許 LDAP 同步自動建立或刪除客戶端的入站。",
+        "noInbounds": "未找到入站。請先在「入站」中建立。",
+        "autoCreate": "自動建立客戶端",
+        "autoDelete": "自動刪除客戶端",
+        "defaultTotalGb": "預設總流量 (GB)",
+        "defaultExpiryDays": "預設到期 (天)",
+        "defaultIpLimit": "預設 IP 限制"
+      },
+      "subFormats": {
+        "packets": "封包",
+        "length": "長度",
+        "interval": "間隔",
+        "maxSplit": "最大分割",
+        "noises": "雜訊",
+        "noiseItem": "雜訊 №{n}",
+        "type": "類型",
+        "packet": "封包",
+        "delayMs": "延遲 (ms)",
+        "applyTo": "套用至",
+        "addNoise": "+ 雜訊",
+        "concurrency": "並發",
+        "xudpConcurrency": "xudp 並發",
+        "xudpUdp443": "xudp UDP 443"
+      },
+      "mux": "Mux",
       "muxDesc": "在已建立的資料流內傳輸多個獨立的資料流",
       "muxDesc": "在已建立的資料流內傳輸多個獨立的資料流",
       "muxSett": "複用器設定",
       "muxSett": "複用器設定",
       "direct": "直接連線",
       "direct": "直接連線",
@@ -758,6 +1059,9 @@
       "save": "儲存",
       "save": "儲存",
       "restart": "重新啟動 Xray",
       "restart": "重新啟動 Xray",
       "restartSuccess": "Xray 已成功重新啟動",
       "restartSuccess": "Xray 已成功重新啟動",
+      "restartOutputTitle": "Xray 重新啟動輸出",
+      "restartConfirmTitle": "重新啟動 xray?",
+      "restartConfirmContent": "使用已儲存的設定重新載入 xray 服務。",
       "stopSuccess": "Xray 已成功停止",
       "stopSuccess": "Xray 已成功停止",
       "restartError": "重新啟動Xray時發生錯誤。",
       "restartError": "重新啟動Xray時發生錯誤。",
       "stopError": "停止Xray時發生錯誤。",
       "stopError": "停止Xray時發生錯誤。",
@@ -765,7 +1069,7 @@
       "advancedTemplate": "高階配置",
       "advancedTemplate": "高階配置",
       "generalConfigs": "常規配置",
       "generalConfigs": "常規配置",
       "generalConfigsDesc": "這些選項將決定常規配置",
       "generalConfigsDesc": "這些選項將決定常規配置",
-      "logConfigs": "日誌",
+      "logConfigs": "記錄",
       "logConfigsDesc": "日誌可能會影響伺服器的效能,建議僅在需要時啟用",
       "logConfigsDesc": "日誌可能會影響伺服器的效能,建議僅在需要時啟用",
       "blockConfigsDesc": "這些選項將阻止使用者連線到特定協議和網站",
       "blockConfigsDesc": "這些選項將阻止使用者連線到特定協議和網站",
       "basicRouting": "基本路由",
       "basicRouting": "基本路由",
@@ -790,10 +1094,12 @@
       "outboundTestUrl": "出站測試 URL",
       "outboundTestUrl": "出站測試 URL",
       "outboundTestUrlDesc": "測試出站連線時使用的 URL",
       "outboundTestUrlDesc": "測試出站連線時使用的 URL",
       "Torrent": "遮蔽 BitTorrent 協議",
       "Torrent": "遮蔽 BitTorrent 協議",
-      "Inbounds": "入站規則",
+      "Inbounds": "入站",
       "InboundsDesc": "接受來自特定客戶端的流量",
       "InboundsDesc": "接受來自特定客戶端的流量",
-      "Outbounds": "出站規則",
+      "Outbounds": "出站",
       "Balancers": "負載均衡",
       "Balancers": "負載均衡",
+      "balancerTagRequired": "標籤為必填",
+      "balancerSelectorRequired": "至少選擇一個出站",
       "OutboundsDesc": "設定出站流量傳出方式",
       "OutboundsDesc": "設定出站流量傳出方式",
       "Routings": "路由規則",
       "Routings": "路由規則",
       "RoutingsDesc": "每條規則的優先順序都很重要",
       "RoutingsDesc": "每條規則的優先順序都很重要",
@@ -832,6 +1138,73 @@
         "edit": "編輯規則",
         "edit": "編輯規則",
         "useComma": "逗號分隔的項目"
         "useComma": "逗號分隔的項目"
       },
       },
+      "routing": {
+        "dragToReorder": "拖曳以重新排序"
+      },
+      "ruleForm": {
+        "sourceIps": "來源 IP",
+        "sourcePort": "來源連接埠",
+        "vlessRoute": "VLESS 路由",
+        "attributes": "屬性",
+        "value": "值",
+        "user": "使用者",
+        "inboundTags": "入站標籤",
+        "outboundTag": "出站標籤",
+        "balancerTag": "均衡器標籤",
+        "balancerTagTooltip": "透過其中一個已設定的負載均衡器路由流量"
+      },
+      "outboundForm": {
+        "tagDuplicate": "該標籤已被其他出站使用",
+        "tagRequired": "標籤為必填",
+        "tagPlaceholder": "唯一標籤",
+        "localIpPlaceholder": "本地 IP",
+        "addressRequired": "地址為必填",
+        "portRequired": "連接埠為必填",
+        "optional": "選用",
+        "udpOverTcp": "UDP over TCP",
+        "uotVersion": "UoT 版本",
+        "inboundTag": "入站標籤",
+        "inboundTagPlaceholder": "用於路由規則的入站標籤",
+        "responseType": "回應類型",
+        "rewriteNetwork": "改寫網路",
+        "unchanged": "(未變更)",
+        "unchangedAddress": "(未變更) 如 1.1.1.1",
+        "rules": "規則",
+        "ruleN": "規則 {n}",
+        "action": "動作",
+        "redirect": "Redirect",
+        "fragment": "Fragment",
+        "finalRules": "最終規則",
+        "overrideXrayPrivateIp": "覆寫 Xray 預設的私有 IP 封鎖",
+        "blockDelay": "阻斷延遲 (ms)",
+        "reverseSniffing": "反向 sniffing",
+        "workers": "Workers",
+        "reserved": "保留",
+        "minUploadInterval": "最小上傳間隔 (ms)",
+        "maxUploadSizeBytes": "最大上傳大小 (位元組)",
+        "uplinkChunkSize": "Uplink chunk 大小",
+        "noGrpcHeader": "無 gRPC 標頭",
+        "maxConcurrency": "最大並發",
+        "maxConnections": "最大連線",
+        "maxReuseTimes": "最大重用次數",
+        "maxRequestTimes": "最大請求次數",
+        "maxReusableSecs": "最大可重用秒數",
+        "keepAlivePeriod": "keep alive 週期",
+        "authPassword": "認證密碼",
+        "visionTestpre": "Vision testpre",
+        "serverNamePlaceholder": "伺服器名稱",
+        "verifyPeerName": "驗證 peer 名稱",
+        "pinnedSha256": "Pinned SHA256",
+        "shortId": "Short ID",
+        "sockopts": "Sockopts",
+        "keepAliveInterval": "keep alive 間隔",
+        "markFwmark": "Mark (fwmark)",
+        "interface": "介面",
+        "ipv6Only": "僅 IPv6",
+        "acceptProxyProtocol": "接受 proxy protocol",
+        "tcpUserTimeoutMs": "TCP user timeout (ms)",
+        "tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
+      },
       "outbound": {
       "outbound": {
         "addOutbound": "新增出站",
         "addOutbound": "新增出站",
         "addReverse": "新增反向",
         "addReverse": "新增反向",
@@ -844,7 +1217,7 @@
         "tagDesc": "唯一標籤",
         "tagDesc": "唯一標籤",
         "address": "地址",
         "address": "地址",
         "reverse": "反向",
         "reverse": "反向",
-        "domain": "域",
+        "domain": "域",
         "type": "類型",
         "type": "類型",
         "bridge": "Bridge",
         "bridge": "Bridge",
         "portal": "Portal",
         "portal": "Portal",
@@ -860,6 +1233,8 @@
         "testSuccess": "測試成功",
         "testSuccess": "測試成功",
         "testFailed": "測試失敗",
         "testFailed": "測試失敗",
         "testError": "測試出站失敗",
         "testError": "測試出站失敗",
+        "testModeTooltip": "TCP: 快速 dial-only 探測。HTTP: 透過 xray 的完整請求。",
+        "testAll": "全部測試",
         "nordvpn": "NordVPN",
         "nordvpn": "NordVPN",
         "accessToken": "訪問令牌",
         "accessToken": "訪問令牌",
         "country": "國家",
         "country": "國家",
@@ -876,6 +1251,16 @@
         "balancerSelectors": "選擇器",
         "balancerSelectors": "選擇器",
         "tag": "標籤",
         "tag": "標籤",
         "tagDesc": "唯一標籤",
         "tagDesc": "唯一標籤",
+        "tagDuplicate": "該標籤已被其他均衡器使用",
+        "tagPlaceholder": "唯一均衡器標籤",
+        "selector": "選擇器",
+        "fallback": "Fallback",
+        "expected": "期望",
+        "expectedPlaceholder": "最佳節點數",
+        "maxRtt": "最大 RTT",
+        "tolerance": "容差",
+        "baselines": "Baselines",
+        "costs": "Costs",
         "balancerDesc": "無法同時使用 balancerTag 和 outboundTag。如果同時使用,則只有 outboundTag 會生效。"
         "balancerDesc": "無法同時使用 balancerTag 和 outboundTag。如果同時使用,則只有 outboundTag 會生效。"
       },
       },
       "wireguard": {
       "wireguard": {
@@ -892,6 +1277,38 @@
         "userLevel": "用戶級別",
         "userLevel": "用戶級別",
         "userLevelDesc": "通過此入站的所有連接都將使用此用戶級別。預設值為 0"
         "userLevelDesc": "通過此入站的所有連接都將使用此用戶級別。預設值為 0"
       },
       },
+      "nord": {
+        "accessToken": "Access token",
+        "privateKey": "私鑰",
+        "noServers": "未找到選定國家/地區的伺服器",
+        "noPublicKey": "選定的伺服器未公布 NordLynx 公鑰。",
+        "outboundAdded": "NordVPN 出站已新增",
+        "outboundUpdated": "NordVPN 出站已更新"
+      },
+      "warp": {
+        "licenseError": "設定 WARP 授權失敗。",
+        "fetchFirst": "請先取得 WARP 設定。",
+        "createAccount": "建立 WARP 帳號",
+        "accessToken": "Access token",
+        "deviceId": "裝置 ID",
+        "licenseKey": "授權金鑰",
+        "privateKey": "私鑰",
+        "deleteAccount": "刪除帳號",
+        "settings": "設定",
+        "licenseKeyLabel": "WARP / WARP+ 授權金鑰",
+        "key": "金鑰",
+        "keyPlaceholder": "26 位 WARP+ 金鑰",
+        "accountInfo": "帳號資訊",
+        "deviceName": "裝置名稱",
+        "deviceModel": "裝置型號",
+        "deviceEnabled": "裝置已啟用",
+        "accountType": "帳號類型",
+        "role": "角色",
+        "warpPlusData": "WARP+ 資料",
+        "quota": "配額",
+        "usage": "使用",
+        "addOutbound": "新增出站"
+      },
       "dns": {
       "dns": {
         "enable": "啟用 DNS",
         "enable": "啟用 DNS",
         "enableDesc": "啟用內建 DNS 伺服器",
         "enableDesc": "啟用內建 DNS 伺服器",
@@ -911,7 +1328,7 @@
         "strategyDesc": "解析域名的總體策略",
         "strategyDesc": "解析域名的總體策略",
         "add": "新增伺服器",
         "add": "新增伺服器",
         "edit": "編輯伺服器",
         "edit": "編輯伺服器",
-        "domains": "域",
+        "domains": "域",
         "expectIPs": "預期 IP",
         "expectIPs": "預期 IP",
         "unexpectIPs": "意外IP",
         "unexpectIPs": "意外IP",
         "useSystemHosts": "使用系統Hosts",
         "useSystemHosts": "使用系統Hosts",
@@ -962,7 +1379,7 @@
     "inbounds": "入站",
     "inbounds": "入站",
     "clients": "客戶端",
     "clients": "客戶端",
     "offline": "🔴 離線",
     "offline": "🔴 離線",
-    "online": "🟢 線",
+    "online": "🟢 線",
     "commands": {
     "commands": {
       "unknown": "❗ 未知命令",
       "unknown": "❗ 未知命令",
       "pleaseChoose": "👇 請選擇:\r\n",
       "pleaseChoose": "👇 請選擇:\r\n",
@@ -992,35 +1409,35 @@
       "2faFailed": "2FA 失敗",
       "2faFailed": "2FA 失敗",
       "report": "🕰 定時報告:{{ .RunTime }}\r\n",
       "report": "🕰 定時報告:{{ .RunTime }}\r\n",
       "datetime": "⏰ 日期時間:{{ .DateTime }}\r\n",
       "datetime": "⏰ 日期時間:{{ .DateTime }}\r\n",
-      "hostname": "💻 主機名:{{ .Hostname }}\r\n",
+      "hostname": "💻 主機: {{ .Hostname }}\r\n",
       "version": "🚀 X-UI 版本:{{ .Version }}\r\n",
       "version": "🚀 X-UI 版本:{{ .Version }}\r\n",
       "xrayVersion": "📡 Xray 版本: {{ .XrayVersion }}\r\n",
       "xrayVersion": "📡 Xray 版本: {{ .XrayVersion }}\r\n",
-      "ipv6": "🌐 IPv6{{ .IPv6 }}\r\n",
-      "ipv4": "🌐 IPv4{{ .IPv4 }}\r\n",
-      "ip": "🌐 IP{{ .IP }}\r\n",
-      "ips": "🔢 IP 地址:\r\n{{ .IPs }}\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": "⏳ 伺服器執行時間:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverUpTime": "⏳ 伺服器執行時間:{{ .UpTime }} {{ .Unit }}\r\n",
       "serverLoad": "📈 伺服器負載:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
       "serverLoad": "📈 伺服器負載:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
-      "serverMemory": "📋 伺服器記憶體:{{ .Current }}/{{ .Total }}\r\n",
-      "tcpCount": "🔹 TCP 連線數:{{ .Count }}\r\n",
-      "udpCount": "🔸 UDP 連線數:{{ .Count }}\r\n",
+      "serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
+      "tcpCount": "🔹 TCP: {{ .Count }}\r\n",
+      "udpCount": "🔸 UDP: {{ .Count }}\r\n",
       "traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
       "traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
-      "xrayStatus": "ℹ️ Xray 狀態:{{ .State }}\r\n",
+      "xrayStatus": "ℹ️ 狀態: {{ .State }}\r\n",
       "username": "👤 使用者名稱:{{ .Username }}\r\n",
       "username": "👤 使用者名稱:{{ .Username }}\r\n",
       "reason": "❗️ 原因:{{ .Reason }}\r\n",
       "reason": "❗️ 原因:{{ .Reason }}\r\n",
       "time": "⏰ 時間:{{ .Time }}\r\n",
       "time": "⏰ 時間:{{ .Time }}\r\n",
-      "inbound": "📍 入站{{ .Remark }}\r\n",
-      "port": "🔌 埠:{{ .Port }}\r\n",
+      "inbound": "📍 入站: {{ .Remark }}\r\n",
+      "port": "🔌 連接埠: {{ .Port }}\r\n",
       "expire": "📅 過期日期:{{ .Time }}\r\n",
       "expire": "📅 過期日期:{{ .Time }}\r\n",
       "expireIn": "📅 剩餘時間:{{ .Time }}\r\n",
       "expireIn": "📅 剩餘時間:{{ .Time }}\r\n",
       "active": "💡 啟用:{{ .Enable }}\r\n",
       "active": "💡 啟用:{{ .Enable }}\r\n",
       "enabled": "🚨 已啟用:{{ .Enable }}\r\n",
       "enabled": "🚨 已啟用:{{ .Enable }}\r\n",
       "online": "🌐 連線狀態:{{ .Status }}\r\n",
       "online": "🌐 連線狀態:{{ .Status }}\r\n",
       "lastOnline": "🔙 上次上線: {{ .Time }}\r\n",
       "lastOnline": "🔙 上次上線: {{ .Time }}\r\n",
-      "email": "📧 郵箱:{{ .Email }}\r\n",
-      "upload": "🔼 上傳↑{{ .Upload }}\r\n",
-      "download": "🔽 下載↓{{ .Download }}\r\n",
-      "total": "📊 總計{{ .UpDown }} / {{ .Total }}\r\n",
+      "email": "📧 電子郵件: {{ .Email }}\r\n",
+      "upload": "🔼 上傳: ↑{{ .Upload }}\r\n",
+      "download": "🔽 下載: ↓{{ .Download }}\r\n",
+      "total": "📊 總計: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
       "TGUser": "👤 電報使用者:{{ .TelegramID }}\r\n",
       "TGUser": "👤 電報使用者:{{ .TelegramID }}\r\n",
       "exhaustedMsg": "🚨 耗盡的 {{ .Type }}:\r\n",
       "exhaustedMsg": "🚨 耗盡的 {{ .Type }}:\r\n",
       "exhaustedCount": "🚨 耗盡的 {{ .Type }} 數量:\r\n",
       "exhaustedCount": "🚨 耗盡的 {{ .Type }} 數量:\r\n",
@@ -1030,7 +1447,7 @@
       "backupTime": "🗄 備份時間:{{ .Time }}\r\n",
       "backupTime": "🗄 備份時間:{{ .Time }}\r\n",
       "refreshedOn": "\r\n📋🔄 重新整理時間:{{ .Time }}\r\n\r\n",
       "refreshedOn": "\r\n📋🔄 重新整理時間:{{ .Time }}\r\n\r\n",
       "yes": "✅ 是的",
       "yes": "✅ 是的",
-      "no": "❌ 沒有",
+      "no": "❌ ",
       "received_id": "🔑📥 ID 已更新。",
       "received_id": "🔑📥 ID 已更新。",
       "received_password": "🔑📥 密碼已更新。",
       "received_password": "🔑📥 密碼已更新。",
       "received_email": "📧📥 電子郵件已更新。",
       "received_email": "📧📥 電子郵件已更新。",
@@ -1077,7 +1494,7 @@
       "ipLimit": "🔢 IP 限制",
       "ipLimit": "🔢 IP 限制",
       "setTGUser": "👤 設定 Telegram 使用者",
       "setTGUser": "👤 設定 Telegram 使用者",
       "toggle": "🔘 啟用/禁用",
       "toggle": "🔘 啟用/禁用",
-      "custom": "🔢 風俗",
+      "custom": "🔢 自訂",
       "confirmNumber": "✅ 確認: {{ .Num }}",
       "confirmNumber": "✅ 確認: {{ .Num }}",
       "confirmNumberAdd": "✅ 確認新增:{{ .Num }}",
       "confirmNumberAdd": "✅ 確認新增:{{ .Num }}",
       "limitTraffic": "🚧 流量限制",
       "limitTraffic": "🚧 流量限制",
@@ -1091,7 +1508,7 @@
       "change_password": "⚙️🔑 密碼",
       "change_password": "⚙️🔑 密碼",
       "change_email": "⚙️📧 電子郵件",
       "change_email": "⚙️📧 電子郵件",
       "change_comment": "⚙️💬 評論",
       "change_comment": "⚙️💬 評論",
-      "change_flow": "⚙️🚦 流控",
+      "change_flow": "⚙️🚦 Flow",
       "ResetAllTraffics": "重設所有流量",
       "ResetAllTraffics": "重設所有流量",
       "SortedTrafficUsageReport": "排序過的流量使用報告"
       "SortedTrafficUsageReport": "排序過的流量使用報告"
     },
     },
@@ -1119,4 +1536,4 @@
       "chooseInbound": "選擇一個入站"
       "chooseInbound": "選擇一個入站"
     }
     }
   }
   }
-}
+}

Vissa filer visades inte eftersom för många filer har ändrats