mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-03 18:13:56 +08:00
🐶 Sync 2026-10-20 22:40:23
This commit is contained in:
1 parent
e813f5cc54
commit
64cea2243a
216 files changed
+11913
-2968
No files matched your search
@@ -7,11 +7,11 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Argon Theme
|
||||
LUCI_DEPENDS:=+luci-base +USE_APK:wget-any +!USE_APK:wget +jsonfilter +ucode-mod-math
|
||||
LUCI_DEPENDS:=+luci-base +USE_APK:wget-any +!USE_APK:wget +jsonfilter +ucode-mod-math +flock +coreutils-timeout
|
||||
# Keep existing translation package names and the argon-config message domain.
|
||||
LUCI_BASENAME:=argon-config
|
||||
PKG_VERSION:=3.0.0
|
||||
PKG_RELEASE:=30
|
||||
PKG_RELEASE:=31
|
||||
PKG_LICENSE:=Apache-2.0 MIT
|
||||
|
||||
# LuCI derives translations independently of the theme version. Keep release
|
||||
|
||||
@@ -89,6 +89,10 @@ Open **System → Argon Config** for login layouts, colors, glass effects, wallp
|
||||
|
||||
Local image and video backgrounds are supported, along with Bing, Unsplash and Wallhaven wallpapers. Unsplash requires an API access key. Browser icons and login logos accept PNG files, 16–1024 pixels per side, up to 1 MiB; browser icons must be square.
|
||||
|
||||
Under **Theme updates**, check the latest stable release, read its release notes and download the package matching your firmware's package manager. Checks use the router's connection to GitHub and cache successful results for five minutes.
|
||||
|
||||
When a newer version is available, choose **Update now** and confirm to install the theme using the firmware’s native APK or OPKG package manager, preserving your Argon configuration. The page shows download, verification and installation status plus installation logs, and resumes monitoring after a page refresh. Reload the page after installation. Automatic installation requires a matching release package and SHA256 digest and does not perform downgrades. It updates the main theme package; separate translation packages remain managed by the system package manager.
|
||||
|
||||
## Screenshots
|
||||
|
||||
Light and dark views of the overview and both login layouts, on desktop and mobile.
|
||||
|
||||
@@ -89,6 +89,10 @@ apk add --allow-untrusted ./luci-theme-argon-*.apk
|
||||
|
||||
背景支持本地图片、视频,以及 Bing、Unsplash、Wallhaven 在线壁纸;Unsplash 需填写 API Access Key。网站图标和登录 Logo 支持 PNG,每边 16–1024 像素、最大 1 MiB,网站图标需为正方形。
|
||||
|
||||
在**主题更新**中手动检查最新稳定版、查看更新日志,并下载与固件包管理器匹配的安装包。检查通过路由器连接 GitHub,成功结果缓存五分钟。
|
||||
|
||||
检测到更高版本后,可点击**立即更新**并确认,通过固件自带的 APK 或 OPKG 安装主题,保留当前 Argon 配置。页面显示下载、校验、安装状态及安装日志,刷新页面后可继续查看进度;安装完成后重新加载页面。自动安装要求正式发布提供对应安装包及 SHA256 校验值,不执行降级。此功能更新主题主包,独立语言包仍由系统包管理器管理。
|
||||
|
||||
## 效果展示
|
||||
|
||||
亮暗两色,展示桌面与手机端的首页和两套登录界面。
|
||||
|
||||
@@ -1210,9 +1210,9 @@ select[multiple] {
|
||||
.login-page .login-form .form-login .errorbox {
|
||||
padding: 0.75rem 1rem;
|
||||
overflow-wrap: anywhere;
|
||||
border-inline-start: 3px solid var(--warning);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--surface-color);
|
||||
background: color-mix(in srgb, var(--warning) 6%, var(--surface-color));
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
text-align: start;
|
||||
@@ -1927,10 +1927,9 @@ span.spinning {
|
||||
margin: clamp(1rem, 4vh, 2rem) auto;
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
gap: var(--field-gap);
|
||||
border: 1px solid transparent;
|
||||
border-inline-start: 3px solid var(--status-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-dialog) !important;
|
||||
background-color: var(--surface-raised) !important;
|
||||
background-color: color-mix(in srgb, var(--status-accent) 4%, var(--surface-raised)) !important;
|
||||
color: var(--text-strong);
|
||||
box-shadow: var(--section-shadow);
|
||||
font-size: 0.875rem;
|
||||
@@ -3241,6 +3240,29 @@ header .header-actions {
|
||||
.cbi-input-file {
|
||||
appearance: auto !important;
|
||||
}
|
||||
.cbi-input-file[type="file"] {
|
||||
padding: 0;
|
||||
padding-inline-end: 0.75rem;
|
||||
line-height: calc(2.5rem - 2px);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cbi-input-file[type="file"]::file-selector-button {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
margin-inline-end: var(--action-gap);
|
||||
padding: 0 0.75rem;
|
||||
border: 0;
|
||||
border-inline-end: 1px solid var(--control-border);
|
||||
border-radius: 0;
|
||||
font: inherit;
|
||||
color: var(--control-text);
|
||||
background-color: var(--surface-active);
|
||||
vertical-align: top;
|
||||
cursor: inherit;
|
||||
appearance: none;
|
||||
}
|
||||
.cbi-input-file::-webkit-file-upload-button {
|
||||
display: inline-block !important;
|
||||
}
|
||||
@@ -4002,8 +4024,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 1px solid transparent;
|
||||
border-inline-start: 3px solid var(--dialog-feedback-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel) !important;
|
||||
background-color: color-mix(in srgb, var(--dialog-feedback-accent) 10%, var(--surface-color)) !important;
|
||||
color: var(--text-strong);
|
||||
@@ -4979,6 +5000,105 @@ pre.command-output {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
[data-page="admin-system-argon-config"] #argon-update [hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-content > p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-versions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
|
||||
gap: var(--field-gap);
|
||||
margin: 0;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-versions dt {
|
||||
margin-bottom: var(--control-gap);
|
||||
color: var(--muted-text);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-versions dd {
|
||||
margin: 0;
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-status[data-state="current"],
|
||||
[data-page="admin-system-argon-config"] .argon-update-status[data-state="complete"] {
|
||||
font-weight: 600;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-status-icon {
|
||||
display: inline-flex;
|
||||
flex: 0 0 1.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border: 1px solid var(--success);
|
||||
border-radius: 50%;
|
||||
color: var(--success);
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-actions > .cbi-button {
|
||||
min-height: 2.5rem;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] #argon-update .argon-update-actions > .cbi-button-neutral {
|
||||
color: var(--text-strong);
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-checked {
|
||||
color: var(--muted-text);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-details {
|
||||
min-width: 0;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-details > summary {
|
||||
cursor: pointer;
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-update-notes {
|
||||
max-height: 22rem;
|
||||
margin: var(--control-gap) 0 0;
|
||||
padding: var(--field-gap);
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel);
|
||||
background-color: var(--surface-muted);
|
||||
color: var(--text-strong);
|
||||
font: inherit;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-system-argon-config"] .argon-color-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -5572,6 +5692,115 @@ pre.command-output {
|
||||
background: var(--input-bg);
|
||||
color: var(--text-color);
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) {
|
||||
display: grid !important;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: start;
|
||||
gap: var(--action-gap) var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-card) !important;
|
||||
background-color: var(--surface-raised) !important;
|
||||
color: var(--text-color);
|
||||
box-shadow: var(--section-shadow);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.6;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:first-child {
|
||||
display: contents;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:first-child > * {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:first-child > * + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:first-child > h4 {
|
||||
grid-column: 1;
|
||||
align-self: center;
|
||||
padding: 0;
|
||||
background: none;
|
||||
color: var(--text-strong);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:first-child > .btn {
|
||||
justify-self: start;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:last-child {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
align-self: center;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) > div:last-child > .btn {
|
||||
margin: 0 !important;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .btn {
|
||||
min-height: 2.25rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--surface-muted);
|
||||
color: var(--text-strong);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) a {
|
||||
color: color-mix(in srgb, var(--link-color) 75%, var(--text-strong));
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.2em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table {
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel);
|
||||
background-color: var(--surface-color);
|
||||
overflow: hidden;
|
||||
font-size: 0.8125rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table > :is(thead, tbody, tfoot) {
|
||||
display: table-row-group;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .tr {
|
||||
display: table-row;
|
||||
background: none;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .th,
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .td {
|
||||
display: table-cell;
|
||||
width: 33.333%;
|
||||
padding: 0.625rem 0.75rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
color: var(--text-strong);
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
text-align: start;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .th {
|
||||
border-top: 0;
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .td:first-child {
|
||||
color: var(--muted-text);
|
||||
font-weight: 400;
|
||||
}
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) .table .td:last-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
[data-page="admin-system-attendedsysupgrade"] #view > p,
|
||||
[data-page="admin-system-attendedsysupgrade-overview"] #view > p {
|
||||
display: flex;
|
||||
@@ -5665,12 +5894,74 @@ pre.command-output {
|
||||
vertical-align: text-top;
|
||||
top: auto;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] #cbi-upload {
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)),
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)) {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed),
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed) {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-value,
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-value {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value,
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-section > .cbi-section-create,
|
||||
[data-page="admin-system-fileassistant"] .cbi-section > .cbi-section-create {
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] #cbi-upload,
|
||||
[data-page="admin-system-fileassistant"] #cbi-upload {
|
||||
margin-top: 0;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-section-table {
|
||||
[data-page="admin-system-filetransfer"] .cbi-section-table,
|
||||
[data-page="admin-system-fileassistant"] .cbi-section-table {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)),
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(var(--form-label-width)) minmax(0, 25rem) auto;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: var(--control-gap) var(--action-gap);
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)) > label.cbi-value,
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) > label.cbi-value {
|
||||
display: block !important;
|
||||
width: auto !important;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)) > .cbi-input-file,
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) > .cbi-input-file {
|
||||
width: 100% !important;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)) > .cbi-button,
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) > .cbi-button {
|
||||
justify-self: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
@container (max-width: 40rem) {
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)),
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
}
|
||||
[data-page="admin-system-filetransfer"] .cbi-value:has( > :is(#ulfile, #dlfile)) > label.cbi-value,
|
||||
[data-page="admin-system-fileassistant"] .cbi-value:has( > :is(#ulfile, #dlfile)) > label.cbi-value {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
[data-page="admin-system-fileassistant"] .fb-container td[class$="-icon"]::before {
|
||||
filter: var(--file-icon-filter);
|
||||
}
|
||||
@@ -6192,36 +6483,47 @@ pre.command-output {
|
||||
[data-page="admin-status-overview"] #view > div:first-child {
|
||||
gap: 0 !important;
|
||||
}
|
||||
[data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"],
|
||||
[data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] {
|
||||
display: flex !important;
|
||||
justify-content: space-evenly !important;
|
||||
flex-wrap: wrap;
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]),
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr)) !important;
|
||||
gap: var(--field-gap);
|
||||
margin: 0 !important;
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
[data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox,
|
||||
[data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox {
|
||||
flex: 0 1 8.5rem;
|
||||
min-width: 8rem !important;
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox,
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox {
|
||||
min-width: 0 !important;
|
||||
max-width: 100% !important;
|
||||
margin: 0 !important;
|
||||
text-align: center;
|
||||
}
|
||||
[data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body,
|
||||
[data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body {
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-head:first-child,
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-head:first-child {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body,
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.75rem 0.5rem;
|
||||
}
|
||||
[data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container,
|
||||
[data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container {
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body .cbi-tooltip-container,
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body .cbi-tooltip-container {
|
||||
font-size: inherit !important;
|
||||
direction: ltr;
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
[dir="rtl"] [data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container .cbi-tooltip,
|
||||
[dir="rtl"] [data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container .cbi-tooltip {
|
||||
[dir="rtl"] [data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body .cbi-tooltip-container .cbi-tooltip,
|
||||
[dir="rtl"] [data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox .ifacebox-body .cbi-tooltip-container .cbi-tooltip {
|
||||
direction: rtl;
|
||||
}
|
||||
[data-page="admin-status"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox > .ifacebox-body:last-child,
|
||||
[data-page="admin-status-overview"] div[style*="display:grid;grid-template-columns:repeat"] .ifacebox > .ifacebox-body:last-child {
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-body:nth-child(2),
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-body:nth-child(2) {
|
||||
flex-grow: 1;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-status"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-body:last-child,
|
||||
[data-page="admin-status-overview"] #view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox > .ifacebox-body:last-child {
|
||||
padding: 0.5rem 0.625rem;
|
||||
}
|
||||
[data-page="admin-status"] .argon-port-traffic,
|
||||
@@ -7292,6 +7594,333 @@ pre.command-output {
|
||||
[data-page="admin-vpn-passwall"] h4 {
|
||||
background: transparent;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)),
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)),
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)),
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)) {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed),
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed),
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed),
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed) {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-value,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-value,
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-value,
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-value {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-value ~ .cbi-value,
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value,
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value,
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-section-descr:not(:empty) ~ .cbi-value {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-section > .cbi-section-create,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-section > .cbi-section-create,
|
||||
[data-page="admin-services-passwall"] .cbi-section > .cbi-section-create,
|
||||
[data-page^="admin-services-passwall-"] .cbi-section > .cbi-section-create {
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-container,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-container,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-container,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-container {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-container > .node-actions,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-container > .node-actions,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-container > .node-actions,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-container > .node-actions {
|
||||
margin: 0 !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-display,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-display,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-display,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-display {
|
||||
display: inline-flex;
|
||||
flex: 0 1 var(--form-control-min-width);
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
width: var(--form-control-min-width) !important;
|
||||
min-width: 0 !important;
|
||||
max-width: 100%;
|
||||
height: 2.5rem !important;
|
||||
min-height: 2.5rem !important;
|
||||
margin: 0 !important;
|
||||
padding: 0.5rem 0.75rem !important;
|
||||
line-height: 1.5rem !important;
|
||||
border: 1px solid var(--control-border) !important;
|
||||
border-radius: var(--radius-control) !important;
|
||||
background-color: var(--select-bg) !important;
|
||||
color: var(--control-text) !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-display:focus,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-display:focus,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-display:focus,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-display:focus {
|
||||
--control-border: var(--control-focus);
|
||||
outline: 0;
|
||||
box-shadow: var(--control-focus-shadow);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-label,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-label,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-label,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-label {
|
||||
flex: 1 1 auto;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
text-align: start;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-arrow-down,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-arrow-down,
|
||||
[data-page="admin-services-passwall"] .lv-arrow-down,
|
||||
[data-page^="admin-services-passwall-"] .lv-arrow-down,
|
||||
[data-page="admin-vpn-passwall"] .lv-arrow-down-small,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-arrow-down-small,
|
||||
[data-page="admin-services-passwall"] .lv-arrow-down-small,
|
||||
[data-page^="admin-services-passwall-"] .lv-arrow-down-small,
|
||||
[data-page="admin-vpn-passwall"] .lv-arrow-right,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-arrow-right,
|
||||
[data-page="admin-services-passwall"] .lv-arrow-right,
|
||||
[data-page^="admin-services-passwall-"] .lv-arrow-right {
|
||||
flex: 0 0 1rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
background-color: currentColor;
|
||||
-webkit-mask: var(--dropdown-arrow-icon) center / contain no-repeat;
|
||||
mask: var(--dropdown-arrow-icon) center / contain no-repeat;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-arrow-right,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-arrow-right,
|
||||
[data-page="admin-services-passwall"] .lv-arrow-right,
|
||||
[data-page^="admin-services-passwall-"] .lv-arrow-right {
|
||||
rotate: -90deg;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel {
|
||||
max-height: min(50vh, 18rem) !important;
|
||||
line-height: 1.5 !important;
|
||||
border: 1px solid var(--border-color) !important;
|
||||
border-radius: var(--radius-panel) !important;
|
||||
background-color: var(--surface-panel) !important;
|
||||
color: var(--dropdown-text) !important;
|
||||
box-shadow: var(--dropdown-shadow);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel > div:first-child,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel > div:first-child,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel > div:first-child,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel > div:first-child {
|
||||
border-color: var(--border-color) !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-dropdown-search,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-dropdown-search,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-dropdown-search,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-dropdown-search {
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid var(--control-border);
|
||||
border-radius: var(--radius-control);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key],
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key],
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key],
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key] {
|
||||
min-height: 2.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: var(--radius-small);
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
text-align: start !important;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
transition: none;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected,
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected:hover,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected:hover,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected:hover,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key].is-selected:hover {
|
||||
background-color: var(--dropdown-selected-bg) !important;
|
||||
color: var(--dropdown-selected-text) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
@media (hover: hover) {
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key]:not(.is-selected):hover,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key]:not(.is-selected):hover,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key]:not(.is-selected):hover,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel.cbi-listvalue-panel li[data-key]:not(.is-selected):hover {
|
||||
background-color: var(--dropdown-hover-bg);
|
||||
}
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-item-label,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-item-label,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-item-label,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-item-label {
|
||||
margin: 0 !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-group-title,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-group-title,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-group-title,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-group-title {
|
||||
gap: var(--control-gap);
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: var(--radius-small);
|
||||
line-height: 1.5;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-group-title > b,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-group-title > b,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-group-title > b,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-group-title > b,
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-group-title > span,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-group-title > span,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-group-title > span,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-group-title > span {
|
||||
margin: 0 !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-group-title > span[id^="group-count-"],
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-group-title > span[id^="group-count-"],
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-group-title > span[id^="group-count-"],
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-group-title > span[id^="group-count-"] {
|
||||
margin-inline-start: auto !important;
|
||||
color: var(--muted-text) !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .lv-dropdown-panel .lv-group-list,
|
||||
[data-page^="admin-vpn-passwall-"] .lv-dropdown-panel .lv-group-list,
|
||||
[data-page="admin-services-passwall"] .lv-dropdown-panel .lv-group-list,
|
||||
[data-page^="admin-services-passwall-"] .lv-dropdown-panel .lv-group-list {
|
||||
margin: var(--control-gap) 0 0;
|
||||
padding-inline-start: var(--control-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"]:has(#maincontent) .lv-dropdown-panel .lv-group-title,
|
||||
[data-page^="admin-vpn-passwall-"]:has(#maincontent) .lv-dropdown-panel .lv-group-title,
|
||||
[data-page="admin-services-passwall"]:has(#maincontent) .lv-dropdown-panel .lv-group-title,
|
||||
[data-page^="admin-services-passwall-"]:has(#maincontent) .lv-dropdown-panel .lv-group-title {
|
||||
background-color: var(--surface-active) !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] .cbi-value-field > .share-toolbar,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-value-field > .share-toolbar,
|
||||
[data-page="admin-services-passwall"] .cbi-value-field > .share-toolbar,
|
||||
[data-page^="admin-services-passwall-"] .cbi-value-field > .share-toolbar {
|
||||
padding-block: 0;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #_passwall_status_fieldset,
|
||||
[data-page^="admin-vpn-passwall-"] #_passwall_status_fieldset,
|
||||
[data-page="admin-services-passwall"] #_passwall_status_fieldset,
|
||||
[data-page^="admin-services-passwall-"] #_passwall_status_fieldset {
|
||||
padding-block: var(--control-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #_passwall_status_fieldset .status .block,
|
||||
[data-page^="admin-vpn-passwall-"] #_passwall_status_fieldset .status .block,
|
||||
[data-page="admin-services-passwall"] #_passwall_status_fieldset .status .block,
|
||||
[data-page^="admin-services-passwall-"] #_passwall_status_fieldset .status .block {
|
||||
margin-block: var(--control-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #_log_fieldset,
|
||||
[data-page^="admin-vpn-passwall-"] #_log_fieldset,
|
||||
[data-page="admin-services-passwall"] #_log_fieldset,
|
||||
[data-page^="admin-services-passwall-"] #_log_fieldset {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #_log_fieldset > .cbi-button,
|
||||
[data-page^="admin-vpn-passwall-"] #_log_fieldset > .cbi-button,
|
||||
[data-page="admin-services-passwall"] #_log_fieldset > .cbi-button,
|
||||
[data-page^="admin-services-passwall-"] #_log_fieldset > .cbi-button {
|
||||
align-self: flex-start;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #_log_fieldset > textarea,
|
||||
[data-page^="admin-vpn-passwall-"] #_log_fieldset > textarea,
|
||||
[data-page="admin-services-passwall"] #_log_fieldset > textarea,
|
||||
[data-page^="admin-services-passwall-"] #_log_fieldset > textarea {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 !important;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version,
|
||||
[data-page^="admin-vpn-passwall-"] #app_version,
|
||||
[data-page="admin-services-passwall"] #app_version,
|
||||
[data-page^="admin-services-passwall-"] #app_version {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version > .cbi-value > .cbi-value-field,
|
||||
[data-page^="admin-vpn-passwall-"] #app_version > .cbi-value > .cbi-value-field,
|
||||
[data-page="admin-services-passwall"] #app_version > .cbi-value > .cbi-value-field,
|
||||
[data-page^="admin-services-passwall-"] #app_version > .cbi-value > .cbi-value-field {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 10rem) auto;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: var(--control-gap) var(--action-gap);
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version > .cbi-value > .cbi-value-field > span:first-child,
|
||||
[data-page^="admin-vpn-passwall-"] #app_version > .cbi-value > .cbi-value-field > span:first-child,
|
||||
[data-page="admin-services-passwall"] #app_version > .cbi-value > .cbi-value-field > span:first-child,
|
||||
[data-page^="admin-services-passwall-"] #app_version > .cbi-value > .cbi-value-field > span:first-child {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version > .cbi-value > .cbi-value-field > input[data-update-app],
|
||||
[data-page^="admin-vpn-passwall-"] #app_version > .cbi-value > .cbi-value-field > input[data-update-app],
|
||||
[data-page="admin-services-passwall"] #app_version > .cbi-value > .cbi-value-field > input[data-update-app],
|
||||
[data-page^="admin-services-passwall-"] #app_version > .cbi-value > .cbi-value-field > input[data-update-app] {
|
||||
grid-column: 2;
|
||||
justify-self: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"],
|
||||
[data-page^="admin-vpn-passwall-"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"],
|
||||
[data-page="admin-services-passwall"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"],
|
||||
[data-page^="admin-services-passwall-"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"] {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
[data-page="admin-vpn-passwall"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"]:empty,
|
||||
[data-page^="admin-vpn-passwall-"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"]:empty,
|
||||
[data-page="admin-services-passwall"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"]:empty,
|
||||
[data-page^="admin-services-passwall-"] #app_version > .cbi-value > .cbi-value-field > span[id$="-detail"]:empty {
|
||||
display: none;
|
||||
}
|
||||
@container (max-width: 40rem) {
|
||||
[data-page="admin-vpn-passwall"] .cbi-value:has(> .cbi-value-field > .share-toolbar) > .cbi-value-title,
|
||||
[data-page^="admin-vpn-passwall-"] .cbi-value:has(> .cbi-value-field > .share-toolbar) > .cbi-value-title,
|
||||
[data-page="admin-services-passwall"] .cbi-value:has(> .cbi-value-field > .share-toolbar) > .cbi-value-title,
|
||||
[data-page^="admin-services-passwall-"] .cbi-value:has(> .cbi-value-field > .share-toolbar) > .cbi-value-title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
[data-page^="admin-vpn-passwall2"] .tr,
|
||||
[data-page^="admin-services-passwall2"] .tr,
|
||||
[data-page^="admin-vpn-passwall2"] .td,
|
||||
|
||||
@@ -11,7 +11,7 @@ return baseclass.extend({
|
||||
var frame = null;
|
||||
var update = function() {
|
||||
frame = null;
|
||||
view.querySelectorAll('.ifacebox[style*="min-width:70px"] > .ifacebox-body:last-child > .cbi-tooltip-container').forEach(function(container) {
|
||||
view.querySelectorAll('.ifacebox:has(> .ifacebox-body > img[src*="/icons/port_"]) > .ifacebox-body:last-child > .cbi-tooltip-container').forEach(function(container) {
|
||||
if (container.querySelector('.argon-port-traffic'))
|
||||
return;
|
||||
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require rpc';
|
||||
'require ui';
|
||||
'require poll';
|
||||
|
||||
var callGet = rpc.declare({ object: 'luci.argon_update', method: 'get', expect: { '': {} }, raise: true });
|
||||
var callCheck = rpc.declare({ object: 'luci.argon_update', method: 'check', expect: { '': {} }, raise: true });
|
||||
var callStatus = rpc.declare({ object: 'luci.argon_update', method: 'status', expect: { '': {} }, raise: true });
|
||||
var callStart = rpc.declare({ object: 'luci.argon_update', method: 'start', params: ['tag', 'package'], expect: { '': {} }, raise: true });
|
||||
var releases = 'https://github.com/jerrykuku/luci-theme-argon/releases';
|
||||
|
||||
function version(value) {
|
||||
if (typeof value !== 'string' || value.length > 80)
|
||||
return null;
|
||||
var m = value.match(/^v?([0-9]+(?:\.[0-9]+){1,3})(?:(?:~|_)(alpha|beta|rc)([0-9]+)|-(alpha|beta|rc)\.([0-9]+))?(?:-r?([0-9]+))?$/);
|
||||
if (!m)
|
||||
return null;
|
||||
var parts = m[1].split('.').map(Number);
|
||||
while (parts.length < 4)
|
||||
parts.push(0);
|
||||
parts.push(m[2] || m[4] ? { alpha: 0, beta: 1, rc: 2 }[m[2] || m[4]] : 3);
|
||||
parts.push(Number(m[3] || m[5] || 0), Number(m[6] || 1));
|
||||
return parts.every(function(n) { return Number.isSafeInteger(n); }) ? parts : null;
|
||||
}
|
||||
|
||||
function compare(a, b) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i])
|
||||
return a[i] < b[i] ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function release(state) {
|
||||
if (!state || typeof state.tag !== 'string' || !/^v?[0-9]+(?:\.[0-9]+){1,3}$/.test(state.tag))
|
||||
return null;
|
||||
var manager = state.package_manager;
|
||||
var file = state[manager === 'opkg' ? 'ipk' : 'apk'];
|
||||
var match = typeof file === 'string' && (manager === 'opkg' ?
|
||||
file.match(/^luci-theme-argon_([0-9][0-9.~a-z-]*)_all\.ipk$/) : manager === 'apk' ?
|
||||
file.match(/^luci-theme-argon-([0-9][0-9._a-z-]*)\.apk$/) : null);
|
||||
var parsed = match && version(match[1]);
|
||||
var tag = version(state.tag);
|
||||
if (!parsed || !tag || parsed[4] !== 3 || parsed.slice(0, 4).join('.') !== tag.slice(0, 4).join('.'))
|
||||
match = null;
|
||||
return { tag: state.tag, file: match ? file : null, version: match ? match[1] : state.tag,
|
||||
parsed: match ? parsed : null };
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
load: function() {
|
||||
return callGet().catch(function() { return null; });
|
||||
},
|
||||
|
||||
render: function(state, map) {
|
||||
var loadedVersion = state && state.current_version;
|
||||
var observedInstallation = !!(state && state.upgrade && state.upgrade.active);
|
||||
var lastPhase = state && state.upgrade && state.upgrade.phase;
|
||||
var busy = false;
|
||||
var monitoring = false;
|
||||
var confirming = false;
|
||||
var starting = false;
|
||||
var attached = false;
|
||||
var current = E('dd');
|
||||
var latest = E('dd');
|
||||
var statusIcon = E('span', { 'class': 'argon-update-status-icon', 'aria-hidden': 'true', 'hidden': true }, '✓');
|
||||
var statusText = E('span');
|
||||
var status = E('p', { 'class': 'argon-update-status', 'role': 'status', 'aria-live': 'polite', 'aria-atomic': 'true' }, [statusIcon, statusText]);
|
||||
var checked = E('p', { 'class': 'argon-update-checked' });
|
||||
var notes = E('pre', { 'class': 'argon-update-notes' });
|
||||
var details = E('details', { 'class': 'argon-update-details', 'hidden': true }, [
|
||||
E('summary', {}, _('Release notes')), notes
|
||||
]);
|
||||
var releaseLink = E('a', { 'class': 'cbi-button cbi-button-neutral', 'href': releases + '/latest', 'target': '_blank', 'rel': 'noopener noreferrer' }, _('View release'));
|
||||
var downloadLink = E('a', { 'class': 'cbi-button cbi-button-neutral', 'hidden': true, 'target': '_blank', 'rel': 'noopener noreferrer' }, _('Download package'));
|
||||
var button = E('button', { 'type': 'button', 'class': 'cbi-button cbi-button-action', 'click': check }, _('Check for updates'));
|
||||
var installButton = E('button', { 'type': 'button', 'class': 'cbi-button cbi-button-action', 'hidden': true, 'click': confirmInstall }, _('Update now'));
|
||||
var reloadButton = E('button', { 'type': 'button', 'class': 'cbi-button cbi-button-neutral', 'hidden': true,
|
||||
'click': function() { window.location.reload(); } }, _('Reload page'));
|
||||
var installHint = E('p', { 'class': 'argon-update-checked', 'hidden': true },
|
||||
_('Automatic installation is unavailable. Download the package to update manually.'));
|
||||
var installLog = E('pre', { 'class': 'argon-update-notes' });
|
||||
var logDetails = E('details', { 'class': 'argon-update-details', 'hidden': true }, [
|
||||
E('summary', {}, _('Installation log')), installLog
|
||||
]);
|
||||
var content = E('div', { 'class': 'argon-update-content' }, [
|
||||
status,
|
||||
E('dl', { 'class': 'argon-update-versions' }, [
|
||||
E('div', {}, [E('dt', {}, _('Current version')), current]),
|
||||
E('div', {}, [E('dt', {}, _('Latest stable version')), latest])
|
||||
]),
|
||||
E('div', { 'class': 'argon-update-actions' }, [button, installButton, reloadButton, releaseLink, downloadLink]),
|
||||
installHint, checked, logDetails, details
|
||||
]);
|
||||
|
||||
function needsReload() {
|
||||
return !!(state && state.upgrade && state.upgrade.phase === 'complete' &&
|
||||
(observedInstallation || loadedVersion && state.current_version !== loadedVersion));
|
||||
}
|
||||
|
||||
function showStatus(message, kind) {
|
||||
statusText.textContent = message;
|
||||
status.setAttribute('data-state', kind || 'idle');
|
||||
statusIcon.hidden = kind !== 'current' && kind !== 'complete';
|
||||
}
|
||||
|
||||
function mayInstall() {
|
||||
var remote = release(state);
|
||||
var local = version(state && state.current_version);
|
||||
return !!(remote && remote.file && remote.parsed && local && compare(local, remote.parsed) < 0 &&
|
||||
state.can_upgrade && map && !map.readonly && !needsReload());
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
var remote = release(state);
|
||||
var local = version(state && state.current_version);
|
||||
var job = state && state.upgrade || {};
|
||||
if (job.active)
|
||||
observedInstallation = true;
|
||||
var active = !!job.active || monitoring;
|
||||
var order = remote && remote.parsed && local ? compare(local, remote.parsed) : null;
|
||||
var available = order !== null && order < 0;
|
||||
var reloadNeeded = needsReload();
|
||||
if (job.phase === 'complete' && lastPhase !== 'complete') {
|
||||
details.open = false;
|
||||
logDetails.open = false;
|
||||
}
|
||||
lastPhase = job.phase;
|
||||
current.textContent = state && state.current_version || _('Unknown version');
|
||||
latest.textContent = remote ? remote.version : _('Not checked yet.');
|
||||
button.disabled = busy || active || confirming;
|
||||
button.className = 'cbi-button ' + (remote ? 'cbi-button-neutral' : 'cbi-button-action');
|
||||
installButton.hidden = !mayInstall();
|
||||
installButton.disabled = busy || active || confirming;
|
||||
installHint.hidden = !(available && !state.can_upgrade && map && !map.readonly && !active && !reloadNeeded);
|
||||
reloadButton.hidden = !reloadNeeded || active;
|
||||
button.textContent = busy ? _('Checking for updates...') : _('Check for updates');
|
||||
content.setAttribute('aria-busy', String(busy));
|
||||
releaseLink.href = remote ? releases + '/tag/' + encodeURIComponent(remote.tag) : releases + '/latest';
|
||||
downloadLink.hidden = !(remote && remote.file) || active || reloadNeeded || order !== null && order >= 0;
|
||||
if (!downloadLink.hidden)
|
||||
downloadLink.href = releases + '/download/' + encodeURIComponent(remote.tag) + '/' + encodeURIComponent(remote.file);
|
||||
checked.hidden = !(remote && Number.isSafeInteger(state.checked_at) && state.checked_at > 0);
|
||||
if (!checked.hidden)
|
||||
checked.textContent = _('Last checked: %s').format(new Date(state.checked_at * 1000).toLocaleString());
|
||||
details.hidden = !remote;
|
||||
notes.textContent = remote && typeof state.notes === 'string' && state.notes.trim() ?
|
||||
state.notes.slice(0, 32768) + (state.notes.length > 32768 ? '\n…' : '') : _('No release notes were published.');
|
||||
logDetails.hidden = typeof job.log !== 'string' || !job.log.trim();
|
||||
installLog.textContent = typeof job.log === 'string' ? job.log.slice(-8192) : '';
|
||||
if (active || job.phase === 'failed' || reloadNeeded)
|
||||
showStatus(jobMessage(job), active ? 'working' : reloadNeeded ? 'complete' : 'error');
|
||||
else if (busy)
|
||||
showStatus(_('Checking for updates...'), 'working');
|
||||
else if (!state || state.result !== 0)
|
||||
showStatus(_('Unable to check for updates. Check the router\'s connection to GitHub and try again.'), 'error');
|
||||
else if (!remote)
|
||||
showStatus(_('Not checked yet.'));
|
||||
else if (!local || !remote.parsed)
|
||||
showStatus(_('Unable to compare this version. View the release for details.'));
|
||||
else
|
||||
showStatus(order < 0 ? _('Update available.') : order === 0 ?
|
||||
_('Your theme is up to date.') : _('The installed version is newer than the latest stable release.'),
|
||||
order === 0 ? 'current' : available ? 'available' : 'idle');
|
||||
}
|
||||
|
||||
function jobMessage(job) {
|
||||
var phases = {
|
||||
starting: _('Preparing the update...'),
|
||||
downloading: _('Downloading the update...'),
|
||||
verifying: _('Verifying the package...'),
|
||||
installing: _('Installing the update. Please wait...'),
|
||||
complete: _('Update installed. Reload the page to use the new version.')
|
||||
};
|
||||
var errors = {
|
||||
network: _('Download failed. Check the router\'s connection to GitHub and try again.'),
|
||||
checksum: _('Package verification failed. Check for updates and try again.'),
|
||||
space: _('Not enough free space to install the update.'),
|
||||
version: _('The installed version has changed. Check for updates again.'),
|
||||
metadata: _('Release information has changed or expired. Check for updates again.'),
|
||||
interrupted: _('The update was interrupted. Check the installed version before trying again.'),
|
||||
install: _('Installation failed. See the installation log for details.')
|
||||
};
|
||||
return job.phase === 'failed' ? errors[job.error] || errors.install :
|
||||
phases[job.phase] || _('Preparing the update...');
|
||||
}
|
||||
|
||||
function stopMonitoring() {
|
||||
monitoring = false;
|
||||
poll.remove(watch);
|
||||
}
|
||||
|
||||
function watch() {
|
||||
if (!content.isConnected) {
|
||||
if (attached)
|
||||
stopMonitoring();
|
||||
return Promise.resolve();
|
||||
}
|
||||
attached = true;
|
||||
return callStatus().then(function(result) {
|
||||
if (result.result !== 0 || !result.upgrade)
|
||||
throw new Error('status unavailable');
|
||||
state = Object.assign({}, state, { current_version: result.current_version, upgrade: result.upgrade });
|
||||
if (result.upgrade.active) {
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
if (starting)
|
||||
return;
|
||||
stopMonitoring();
|
||||
return callGet().then(function(result) {
|
||||
if (result.result === 0)
|
||||
state = result;
|
||||
}).catch(function() {}).then(function() {
|
||||
if (state.upgrade && state.upgrade.active)
|
||||
monitor();
|
||||
refresh();
|
||||
});
|
||||
}).catch(function() {
|
||||
showStatus(_('Unable to read update progress. Reconnecting...'), 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function monitor() {
|
||||
if (!monitoring) {
|
||||
monitoring = true;
|
||||
poll.add(watch, 2);
|
||||
}
|
||||
}
|
||||
|
||||
function install() {
|
||||
var remote = release(state);
|
||||
if (busy || monitoring || !mayInstall())
|
||||
return Promise.resolve();
|
||||
starting = true;
|
||||
monitor();
|
||||
refresh();
|
||||
return callStart(remote.tag, remote.file).then(function(result) {
|
||||
starting = false;
|
||||
if (result.result !== 0) {
|
||||
stopMonitoring();
|
||||
refresh();
|
||||
showStatus(result.result === 3 ? _('Release information has changed or expired. Check for updates again.') :
|
||||
result.result === 5 ? _('The installed version has changed. Check for updates again.') :
|
||||
_('Unable to start the update. Check for updates and try again.'), 'error');
|
||||
if (result.result === 3 || result.result === 5) {
|
||||
state.can_upgrade = false;
|
||||
installButton.hidden = true;
|
||||
}
|
||||
if (result.result === 4) {
|
||||
monitor();
|
||||
return watch();
|
||||
}
|
||||
return;
|
||||
}
|
||||
state.upgrade = result.upgrade;
|
||||
monitor();
|
||||
refresh();
|
||||
}).catch(function() {
|
||||
starting = false;
|
||||
// A lost reply does not mean the worker failed to start. Poll before
|
||||
// allowing another installation request.
|
||||
showStatus(_('Unable to read update progress. Reconnecting...'), 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function confirmInstall() {
|
||||
var remote = release(state);
|
||||
if (busy || monitoring || confirming || !mayInstall())
|
||||
return;
|
||||
confirming = true;
|
||||
refresh();
|
||||
ui.showModal(_('Update Argon to %s?').format(remote.version), [
|
||||
E('p', {}, _('The theme will be updated using the system package manager. Your Argon settings will be preserved.')),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', { 'type': 'button', 'class': 'btn', 'click': function() {
|
||||
confirming = false;
|
||||
ui.hideModal();
|
||||
refresh();
|
||||
} }, _('Cancel')),
|
||||
' ',
|
||||
E('button', { 'type': 'button', 'class': 'cbi-button cbi-button-action', 'click': function() {
|
||||
confirming = false;
|
||||
ui.hideModal();
|
||||
return install();
|
||||
} }, _('Update now'))
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
function check() {
|
||||
if (busy || monitoring || confirming)
|
||||
return Promise.resolve();
|
||||
busy = true;
|
||||
refresh();
|
||||
return callCheck().then(function(result) {
|
||||
if (result.result !== 0 || !release(result))
|
||||
throw new Error('update check failed');
|
||||
state = result;
|
||||
busy = false;
|
||||
refresh();
|
||||
var remote = release(state);
|
||||
var local = version(state.current_version);
|
||||
details.open = !!(remote && remote.parsed && local && compare(local, remote.parsed) < 0 && !needsReload());
|
||||
if (state.upgrade && state.upgrade.active)
|
||||
monitor();
|
||||
}).catch(function() {
|
||||
busy = false;
|
||||
refresh();
|
||||
showStatus(_('Unable to check for updates. Check the router\'s connection to GitHub and try again.'), 'error');
|
||||
});
|
||||
}
|
||||
if (state && state.upgrade && state.upgrade.active)
|
||||
monitor();
|
||||
refresh();
|
||||
return E('div', { 'class': 'cbi-section', 'id': 'argon-update' }, [
|
||||
E('h3', {}, _('Theme updates')), content
|
||||
]);
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require argon.branding as branding';
|
||||
'require argon.updates as updates';
|
||||
'require fs';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
@@ -103,7 +104,8 @@ return view.extend({
|
||||
ui.addNotification(null, E('p', _('Failed to list background files: %s.').format(e.message)));
|
||||
return [];
|
||||
}),
|
||||
branding.load()
|
||||
branding.load(),
|
||||
updates.load()
|
||||
]);
|
||||
},
|
||||
|
||||
@@ -113,6 +115,9 @@ return view.extend({
|
||||
m = new form.Map('argon', _('Argon theme configuration'),
|
||||
_('Here you can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos. Chrome is recommended.'));
|
||||
|
||||
s = m.section(form.TypedSection);
|
||||
s.render = function() { return updates.render(data[4], this.map); };
|
||||
|
||||
s = m.section(form.TypedSection, 'global', _('Theme configuration'));
|
||||
s.addremove = false;
|
||||
s.anonymous = true;
|
||||
|
||||
@@ -75,10 +75,9 @@
|
||||
margin: clamp(1rem, 4vh, 2rem) auto;
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
gap: var(--field-gap);
|
||||
border: 1px solid transparent;
|
||||
border-inline-start: 3px solid var(--status-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-dialog) !important;
|
||||
background-color: var(--surface-raised) !important;
|
||||
background-color: color-mix(in srgb, var(--status-accent) 4%, var(--surface-raised)) !important;
|
||||
color: var(--text-strong);
|
||||
box-shadow: var(--section-shadow);
|
||||
font-size: .875rem;
|
||||
|
||||
@@ -245,6 +245,33 @@
|
||||
.cbi-input-file {
|
||||
appearance: auto !important;
|
||||
|
||||
// File pickers include their own button. A text field's vertical padding
|
||||
// leaves too little space for that button and clips its lower edge.
|
||||
&[type="file"] {
|
||||
padding: 0;
|
||||
padding-inline-end: .75rem;
|
||||
line-height: calc(2.5rem - 2px);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
&::file-selector-button {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
margin-inline-end: var(--action-gap);
|
||||
padding: 0 .75rem;
|
||||
border: 0;
|
||||
border-inline-end: 1px solid var(--control-border);
|
||||
border-radius: 0;
|
||||
font: inherit;
|
||||
color: var(--control-text);
|
||||
background-color: var(--surface-active);
|
||||
vertical-align: top;
|
||||
cursor: inherit;
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-file-upload-button {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
@@ -234,8 +234,7 @@
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: .75rem 1rem;
|
||||
border: 1px solid transparent;
|
||||
border-inline-start: 3px solid var(--dialog-feedback-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel) !important;
|
||||
background-color: color-mix(in srgb, var(--dialog-feedback-accent) 10%, var(--surface-color)) !important;
|
||||
color: var(--text-strong);
|
||||
|
||||
@@ -68,6 +68,35 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// Older Lua CBI forms omit the body inset supplied by modern tab containers.
|
||||
// Page adapters opt in so headings, descriptions and fields share one rhythm.
|
||||
.legacy-cbi-section-spacing() {
|
||||
.cbi-section {
|
||||
> .cbi-section-node:not(.cbi-section-node-tabbed):where(:has(> .cbi-value, > [id] > .cbi-value)) {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
|
||||
// Descriptions already inset the body, but a painted heading is a separate
|
||||
// surface: its bottom padding cannot supply space below that surface.
|
||||
> .cbi-section-descr:not(:empty) ~ .cbi-section-node:not(.cbi-section-node-tabbed) {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
|
||||
> .cbi-value {
|
||||
padding-block: var(--field-gap);
|
||||
}
|
||||
|
||||
> .cbi-value ~ .cbi-value,
|
||||
> .cbi-section-descr:not(:empty) ~ .cbi-value {
|
||||
padding-block-start: 0;
|
||||
}
|
||||
|
||||
> .cbi-section-create {
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cbi-map-descr+fieldset {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,121 @@
|
||||
// out: false
|
||||
|
||||
[data-page="admin-system-argon-config"] {
|
||||
#argon-update [hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.argon-update-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
|
||||
> p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.argon-update-versions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(~"min(100%, 16rem)", 1fr));
|
||||
gap: var(--field-gap);
|
||||
margin: 0;
|
||||
|
||||
dt {
|
||||
margin-bottom: var(--control-gap);
|
||||
color: var(--muted-text);
|
||||
font-size: .8125rem;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0;
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
.argon-update-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
color: var(--text-strong);
|
||||
|
||||
&[data-state="current"],
|
||||
&[data-state="complete"] {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.argon-update-status-icon {
|
||||
display: inline-flex;
|
||||
flex: 0 0 1.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border: 1px solid var(--success);
|
||||
border-radius: 50%;
|
||||
color: var(--success);
|
||||
font-size: .8125rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.argon-update-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
|
||||
> .cbi-button {
|
||||
min-height: 2.5rem;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
#argon-update .argon-update-actions > .cbi-button-neutral {
|
||||
color: var(--text-strong);
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
|
||||
.argon-update-checked {
|
||||
color: var(--muted-text);
|
||||
font-size: .8125rem;
|
||||
}
|
||||
|
||||
.argon-update-details {
|
||||
min-width: 0;
|
||||
|
||||
> summary {
|
||||
cursor: pointer;
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.argon-update-notes {
|
||||
max-height: 22rem;
|
||||
margin: var(--control-gap) 0 0;
|
||||
padding: var(--field-gap);
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel);
|
||||
background-color: var(--surface-muted);
|
||||
color: var(--text-strong);
|
||||
font: inherit;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.argon-color-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,5 +1,134 @@
|
||||
// out: false
|
||||
|
||||
// The overview's native firmware reminder is inserted outside #view.
|
||||
// Match its upgrade link so the styling also applies through the homepage route.
|
||||
#maincontent > .alert-message.notice:has(a[href$="/admin/system/attendedsysupgrade"]) {
|
||||
display: grid !important;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: start;
|
||||
gap: var(--action-gap) var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-card) !important;
|
||||
background-color: var(--surface-raised) !important;
|
||||
color: var(--text-color);
|
||||
box-shadow: var(--section-shadow);
|
||||
font-size: .875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.6;
|
||||
|
||||
// Keep LuCI's nodes and handlers; share the heading row with Dismiss.
|
||||
> div:first-child {
|
||||
display: contents;
|
||||
|
||||
> * {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
|
||||
+ * {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> h4 {
|
||||
grid-column: 1;
|
||||
align-self: center;
|
||||
padding: 0;
|
||||
background: none;
|
||||
color: var(--text-strong);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
> .btn {
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-child {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
align-self: center;
|
||||
|
||||
> .btn {
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
min-height: 2.25rem;
|
||||
padding: .375rem .75rem;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--surface-muted);
|
||||
color: var(--text-strong);
|
||||
font-size: .8125rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
a {
|
||||
color: color-mix(in srgb, var(--link-color) 75%, var(--text-strong));
|
||||
text-decoration: underline;
|
||||
text-underline-offset: .2em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-panel);
|
||||
background-color: var(--surface-color);
|
||||
overflow: hidden;
|
||||
font-size: .8125rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
|
||||
> :is(thead, tbody, tfoot) {
|
||||
display: table-row-group;
|
||||
}
|
||||
|
||||
.tr {
|
||||
display: table-row;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.th,
|
||||
.td {
|
||||
display: table-cell;
|
||||
width: 33.333%;
|
||||
padding: .625rem .75rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
color: var(--text-strong);
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
text-align: start;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.th {
|
||||
border-top: 0;
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
|
||||
.td:first-child {
|
||||
color: var(--muted-text);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.td:last-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// System - Attended Sysupgrade
|
||||
[data-page="admin-system-attendedsysupgrade"],
|
||||
[data-page="admin-system-attendedsysupgrade-overview"] {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// out: false
|
||||
|
||||
// System - File Transfer
|
||||
[data-page="admin-system-filetransfer"] {
|
||||
[data-page="admin-system-filetransfer"],
|
||||
[data-page="admin-system-fileassistant"] {
|
||||
.legacy-cbi-section-spacing();
|
||||
|
||||
#cbi-upload {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -9,4 +12,49 @@
|
||||
.cbi-section-table {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
// Legacy upload/download templates use a row class on their labels and
|
||||
// fixed inline widths. Keep each label, field and action in one form row.
|
||||
.cbi-value:has(> :is(#ulfile, #dlfile)) {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(var(--form-label-width)) minmax(0, 25rem) auto;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: var(--control-gap) var(--action-gap);
|
||||
|
||||
> label.cbi-value {
|
||||
display: block !important;
|
||||
width: auto !important;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
> .cbi-input-file {
|
||||
width: 100% !important;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
> .cbi-button {
|
||||
justify-self: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the page selectors explicit inside container queries: Less 4 does not
|
||||
// retain an enclosing selector when bubbling a nested @container rule.
|
||||
@container (max-width: 40rem) {
|
||||
[data-page="admin-system-filetransfer"],
|
||||
[data-page="admin-system-fileassistant"] {
|
||||
.cbi-value:has(> :is(#ulfile, #dlfile)) {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
|
||||
> label.cbi-value {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,19 +75,24 @@
|
||||
gap: 0 !important;
|
||||
}
|
||||
|
||||
// Native port status uses a 70px grid. Keep the counters readable and wrap
|
||||
// whole cards when multiple physical ports are present.
|
||||
div[style*="display:grid;grid-template-columns:repeat"] {
|
||||
display: flex !important;
|
||||
justify-content: space-evenly !important;
|
||||
flex-wrap: wrap;
|
||||
// Match native port cards by their icons, independently of inline CSS formatting.
|
||||
#view div:has(> .ifacebox > .ifacebox-body > img[src*="/icons/port_"]) {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(auto-fit, minmax(~"min(100%, 8.5rem)", 1fr)) !important;
|
||||
gap: var(--field-gap);
|
||||
margin: 0 !important;
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
|
||||
.ifacebox {
|
||||
flex: 0 1 8.5rem;
|
||||
min-width: 8rem !important;
|
||||
> .ifacebox {
|
||||
min-width: 0 !important;
|
||||
max-width: 100% !important;
|
||||
margin: 0 !important;
|
||||
text-align: center;
|
||||
|
||||
> .ifacebox-head:first-child {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.ifacebox-body {
|
||||
font-size: .75rem;
|
||||
padding: .75rem .5rem;
|
||||
@@ -103,6 +108,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .ifacebox-body:nth-child(2) {
|
||||
flex-grow: 1;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
> .ifacebox-body:last-child {
|
||||
padding: .5rem .625rem;
|
||||
}
|
||||
|
||||
@@ -4,3 +4,241 @@
|
||||
[data-page="admin-vpn-passwall"] h4 {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[data-page="admin-vpn-passwall"],
|
||||
[data-page^="admin-vpn-passwall-"],
|
||||
[data-page="admin-services-passwall"],
|
||||
[data-page^="admin-services-passwall-"] {
|
||||
.legacy-cbi-section-spacing();
|
||||
|
||||
.lv-dropdown-container {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
|
||||
> .node-actions {
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Passwall snapshots select styles into per-ID rules, including the native
|
||||
// arrow's padding and resolved colors. Keep the custom control responsive
|
||||
// and its colors live when Argon's appearance changes.
|
||||
.lv-dropdown-display {
|
||||
display: inline-flex;
|
||||
flex: 0 1 var(--form-control-min-width);
|
||||
align-items: center;
|
||||
gap: var(--control-gap);
|
||||
width: var(--form-control-min-width) !important;
|
||||
min-width: 0 !important;
|
||||
max-width: 100%;
|
||||
height: 2.5rem !important;
|
||||
min-height: 2.5rem !important;
|
||||
margin: 0 !important;
|
||||
padding: .5rem .75rem !important;
|
||||
line-height: 1.5rem !important;
|
||||
border: 1px solid var(--control-border) !important;
|
||||
border-radius: var(--radius-control) !important;
|
||||
background-color: var(--select-bg) !important;
|
||||
color: var(--control-text) !important;
|
||||
|
||||
&:focus {
|
||||
--control-border: var(--control-focus);
|
||||
outline: 0;
|
||||
box-shadow: var(--control-focus-shadow);
|
||||
}
|
||||
}
|
||||
|
||||
.lv-dropdown-label {
|
||||
flex: 1 1 auto;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
text-align: start;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.lv-arrow-down,
|
||||
.lv-arrow-down-small,
|
||||
.lv-arrow-right {
|
||||
flex: 0 0 1rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
background-color: currentColor;
|
||||
-webkit-mask: var(--dropdown-arrow-icon) center / contain no-repeat;
|
||||
mask: var(--dropdown-arrow-icon) center / contain no-repeat;
|
||||
}
|
||||
|
||||
.lv-arrow-right {
|
||||
rotate: -90deg;
|
||||
}
|
||||
|
||||
// The plugin moves opened menus to body, outside the form container.
|
||||
.lv-dropdown-panel {
|
||||
max-height: ~"min(50vh, 18rem)" !important;
|
||||
line-height: 1.5 !important;
|
||||
border: 1px solid var(--border-color) !important;
|
||||
border-radius: var(--radius-panel) !important;
|
||||
background-color: var(--surface-panel) !important;
|
||||
color: var(--dropdown-text) !important;
|
||||
box-shadow: var(--dropdown-shadow);
|
||||
|
||||
> div:first-child {
|
||||
border-color: var(--border-color) !important;
|
||||
}
|
||||
|
||||
.lv-dropdown-search {
|
||||
padding: .5rem .75rem;
|
||||
border: 1px solid var(--control-border);
|
||||
border-radius: var(--radius-control);
|
||||
}
|
||||
|
||||
&.cbi-listvalue-panel li[data-key] {
|
||||
min-height: 2.5rem;
|
||||
padding: .5rem .75rem;
|
||||
border-radius: var(--radius-small);
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
text-align: start !important;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
transition: none;
|
||||
|
||||
&.is-selected,
|
||||
&.is-selected:hover {
|
||||
background-color: var(--dropdown-selected-bg) !important;
|
||||
color: var(--dropdown-selected-text) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:not(.is-selected):hover {
|
||||
background-color: var(--dropdown-hover-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lv-item-label {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.lv-group-title {
|
||||
gap: var(--control-gap);
|
||||
padding: .5rem .75rem;
|
||||
border-radius: var(--radius-small);
|
||||
line-height: 1.5;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
|
||||
> b,
|
||||
> span {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
> span[id^="group-count-"] {
|
||||
margin-inline-start: auto !important;
|
||||
color: var(--muted-text) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.lv-group-list {
|
||||
margin: var(--control-gap) 0 0;
|
||||
padding-inline-start: var(--control-gap);
|
||||
}
|
||||
}
|
||||
|
||||
// Match the ID specificity of the plugin's !important group-title color,
|
||||
// including after the menu has been moved outside #maincontent.
|
||||
&:has(#maincontent) .lv-dropdown-panel .lv-group-title {
|
||||
background-color: var(--surface-active) !important;
|
||||
}
|
||||
|
||||
// The section body supplies the toolbar's vertical inset.
|
||||
.cbi-value-field > .share-toolbar {
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
#_passwall_status_fieldset {
|
||||
padding-block: var(--control-gap);
|
||||
|
||||
.status .block {
|
||||
margin-block: var(--control-gap);
|
||||
}
|
||||
}
|
||||
|
||||
#_log_fieldset {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
padding: var(--field-gap) var(--section-inset);
|
||||
|
||||
> .cbi-button {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
> textarea {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
#app_version {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--field-gap);
|
||||
|
||||
> .cbi-value > .cbi-value-field {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 10rem) auto;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: var(--control-gap) var(--action-gap);
|
||||
|
||||
> span:first-child {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
|
||||
> input[data-update-app] {
|
||||
grid-column: 2;
|
||||
justify-self: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
> span[id$="-detail"] {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@container (max-width: 40rem) {
|
||||
[data-page="admin-vpn-passwall"],
|
||||
[data-page^="admin-vpn-passwall-"],
|
||||
[data-page="admin-services-passwall"],
|
||||
[data-page^="admin-services-passwall-"] {
|
||||
// Its label is an ideographic space in the native template; when
|
||||
// fields stack, it otherwise leaves a blank line above the actions.
|
||||
.cbi-value:has(> .cbi-value-field > .share-toolbar) > .cbi-value-title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,9 +131,9 @@
|
||||
.errorbox {
|
||||
padding: .75rem 1rem;
|
||||
overflow-wrap: anywhere;
|
||||
border-inline-start: 3px solid var(--warning);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--surface-color);
|
||||
background: color-mix(in srgb, var(--warning) 6%, var(--surface-color));
|
||||
color: var(--text-strong);
|
||||
line-height: 1.5;
|
||||
text-align: start;
|
||||
|
||||
@@ -380,3 +380,155 @@ msgstr "[الوضع الداكن] الشفافية"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "قيمة لون صالحة بصيغة HEX"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "ملاحظات الإصدار"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "عرض الإصدار"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "تنزيل الحزمة"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "التحقق من وجود تحديثات"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "الإصدار الحالي"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "أحدث إصدار مستقر"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "إصدار غير معروف"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "لم يتم التحقق بعد."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "جارٍ التحقق من وجود تحديثات..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "آخر تحقق: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "لم تُنشر ملاحظات لهذا الإصدار."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "تعذر التحقق من وجود تحديثات. تحقق من اتصال الموجّه بـ GitHub وحاول مجددًا."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "تعذرت مقارنة هذا الإصدار. اعرض الإصدار لمعرفة التفاصيل."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "يتوفر تحديث."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "السمة محدّثة."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "الإصدار المثبّت أحدث من آخر إصدار مستقر."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "تحديثات السمة"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "التحديث الآن"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "إعادة تحميل الصفحة"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "التثبيت التلقائي غير متاح. نزّل الحزمة للتحديث يدوياً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "سجل التثبيت"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "جارٍ تجهيز التحديث..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "جارٍ تنزيل التحديث..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "جارٍ التحقق من الحزمة..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "جارٍ تثبيت التحديث. يُرجى الانتظار..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "تم تثبيت التحديث. أعد تحميل الصفحة لاستخدام الإصدار الجديد."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "فشل التنزيل. تحقق من اتصال الموجّه بـ GitHub وحاول مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "فشل التحقق من الحزمة. تحقق من التحديثات وحاول مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "لا توجد مساحة خالية كافية لتثبيت التحديث."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "تغيّر الإصدار المثبّت. تحقق من التحديثات مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "تغيّرت معلومات الإصدار أو انتهت صلاحيتها. تحقق من التحديثات مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "انقطع التحديث. تحقق من الإصدار المثبّت قبل المحاولة مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "فشل التثبيت. راجع سجل التثبيت لمزيد من التفاصيل."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "تعذرت قراءة تقدم التحديث. جارٍ إعادة الاتصال..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "تعذر بدء التحديث. تحقق من التحديثات وحاول مجدداً."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "هل تريد تحديث Argon إلى %s؟"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "سيُحدَّث المظهر باستخدام مدير حزم النظام. ستُحفظ إعدادات Argon الحالية."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "إلغاء"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Dunkler Modus] Transparenz"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "gültiger HEX-Farbwert"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Versionshinweise"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Veröffentlichung ansehen"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Paket herunterladen"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Nach Updates suchen"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Installierte Version"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Neueste stabile Version"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Unbekannte Version"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Noch nicht geprüft."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Updates werden gesucht..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Zuletzt geprüft: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Für diese Version wurden keine Versionshinweise veröffentlicht."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Updates konnten nicht geprüft werden. Prüfen Sie die Verbindung des Routers zu GitHub und versuchen Sie es erneut."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Diese Version kann nicht verglichen werden. Details finden Sie auf der Veröffentlichungsseite."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Ein Update ist verfügbar."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Ihr Theme ist auf dem neuesten Stand."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Die installierte Version ist neuer als die neueste stabile Version."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Theme-Updates"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Jetzt aktualisieren"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Seite neu laden"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Die automatische Installation ist nicht verfügbar. Laden Sie das Paket für eine manuelle Aktualisierung herunter."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Installationsprotokoll"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Aktualisierung wird vorbereitet..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Aktualisierung wird heruntergeladen..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Paket wird überprüft..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Aktualisierung wird installiert. Bitte warten..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Aktualisierung installiert. Laden Sie die Seite neu, um die neue Version zu verwenden."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Download fehlgeschlagen. Prüfen Sie die Verbindung des Routers zu GitHub und versuchen Sie es erneut."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Paketprüfung fehlgeschlagen. Suchen Sie erneut nach Aktualisierungen und versuchen Sie es noch einmal."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Nicht genügend freier Speicherplatz für die Aktualisierung."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Die installierte Version hat sich geändert. Suchen Sie erneut nach Aktualisierungen."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Die Versionsinformationen haben sich geändert oder sind abgelaufen. Suchen Sie erneut nach Aktualisierungen."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Die Aktualisierung wurde unterbrochen. Prüfen Sie vor einem erneuten Versuch die installierte Version."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Installation fehlgeschlagen. Einzelheiten finden Sie im Installationsprotokoll."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Der Aktualisierungsfortschritt kann nicht gelesen werden. Verbindung wird wiederhergestellt..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Die Aktualisierung kann nicht gestartet werden. Suchen Sie erneut nach Aktualisierungen und versuchen Sie es noch einmal."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Argon auf %s aktualisieren?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Das Theme wird mit der Paketverwaltung des Systems aktualisiert. Ihre Argon-Einstellungen bleiben erhalten."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
@@ -382,3 +382,155 @@ msgstr "[Modo oscuro] Transparencia"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "un valor de color HEX válido"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Notas de la versión"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Ver publicación"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Descargar paquete"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Buscar actualizaciones"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Versión actual"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Última versión estable"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Versión desconocida"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Aún no se ha comprobado."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Buscando actualizaciones..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Última comprobación: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "No se publicaron notas para esta versión."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "No se pudieron buscar actualizaciones. Compruebe la conexión del router con GitHub e inténtelo de nuevo."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "No se puede comparar esta versión. Consulte la publicación para más detalles."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Hay una actualización disponible."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "El tema está actualizado."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "La versión instalada es más reciente que la última versión estable."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Actualizaciones del tema"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Actualizar ahora"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Recargar página"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "La instalación automática no está disponible. Descargue el paquete para actualizar manualmente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Registro de instalación"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Preparando la actualización..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Descargando la actualización..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Verificando el paquete..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Instalando la actualización. Espere..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Actualización instalada. Recargue la página para utilizar la nueva versión."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Error de descarga. Compruebe la conexión del router con GitHub e inténtelo de nuevo."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Error al verificar el paquete. Vuelva a buscar actualizaciones e inténtelo de nuevo."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "No hay suficiente espacio libre para instalar la actualización."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "La versión instalada ha cambiado. Vuelva a buscar actualizaciones."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "La información de la versión ha cambiado o ha caducado. Vuelva a buscar actualizaciones."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "La actualización se ha interrumpido. Compruebe la versión instalada antes de intentarlo de nuevo."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Error de instalación. Consulte el registro de instalación para obtener más información."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "No se puede leer el progreso de la actualización. Reconectando..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "No se puede iniciar la actualización. Vuelva a buscar actualizaciones e inténtelo de nuevo."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "¿Actualizar Argon a %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "El tema se actualizará con el gestor de paquetes del sistema. Se conservará su configuración de Argon."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Mode sombre] Transparence"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "une valeur de couleur HEX valide"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Notes de version"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Voir la publication"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Télécharger le paquet"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Rechercher des mises à jour"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Version actuelle"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Dernière version stable"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Version inconnue"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Aucune vérification effectuée."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Recherche de mises à jour..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Dernière vérification : %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Aucune note n’a été publiée pour cette version."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Impossible de rechercher les mises à jour. Vérifiez la connexion du routeur à GitHub, puis réessayez."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Impossible de comparer cette version. Consultez la publication pour plus de détails."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Une mise à jour est disponible."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Votre thème est à jour."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "La version installée est plus récente que la dernière version stable."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Mises à jour du thème"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Mettre à jour maintenant"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Recharger la page"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "L’installation automatique est indisponible. Téléchargez le paquet pour une mise à jour manuelle."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Journal d’installation"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Préparation de la mise à jour..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Téléchargement de la mise à jour..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Vérification du paquet..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Installation de la mise à jour. Veuillez patienter..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Mise à jour installée. Rechargez la page pour utiliser la nouvelle version."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Échec du téléchargement. Vérifiez la connexion du routeur à GitHub et réessayez."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Échec de la vérification du paquet. Recherchez à nouveau les mises à jour et réessayez."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Espace libre insuffisant pour installer la mise à jour."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "La version installée a changé. Recherchez à nouveau les mises à jour."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Les informations de version ont changé ou ont expiré. Recherchez à nouveau les mises à jour."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "La mise à jour a été interrompue. Vérifiez la version installée avant de réessayer."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Échec de l’installation. Consultez le journal d’installation pour plus de détails."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Impossible de lire la progression. Reconnexion en cours..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Impossible de lancer la mise à jour. Recherchez à nouveau les mises à jour et réessayez."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Mettre à jour Argon vers %s ?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Le thème sera mis à jour avec le gestionnaire de paquets du système. Vos paramètres Argon seront conservés."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Modalità scura] Trasparenza"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "un valore di colore HEX valido"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Note di rilascio"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Visualizza rilascio"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Scarica pacchetto"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Controlla aggiornamenti"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Versione attuale"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Ultima versione stabile"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Versione sconosciuta"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Controllo non ancora eseguito."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Ricerca aggiornamenti..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Ultimo controllo: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Non sono state pubblicate note per questa versione."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Impossibile controllare gli aggiornamenti. Verificare la connessione del router a GitHub e riprovare."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Impossibile confrontare questa versione. Consultare il rilascio per i dettagli."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "È disponibile un aggiornamento."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Il tema è aggiornato."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "La versione installata è più recente dell’ultima versione stabile."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Aggiornamenti del tema"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Aggiorna ora"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Ricarica pagina"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "L’installazione automatica non è disponibile. Scarica il pacchetto per aggiornare manualmente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Registro di installazione"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Preparazione dell’aggiornamento..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Download dell’aggiornamento..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Verifica del pacchetto..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Installazione dell’aggiornamento. Attendere..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Aggiornamento installato. Ricarica la pagina per usare la nuova versione."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Download non riuscito. Controlla la connessione del router a GitHub e riprova."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Verifica del pacchetto non riuscita. Cerca di nuovo gli aggiornamenti e riprova."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Spazio libero insufficiente per installare l’aggiornamento."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "La versione installata è cambiata. Cerca di nuovo gli aggiornamenti."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Le informazioni sulla versione sono cambiate o scadute. Cerca di nuovo gli aggiornamenti."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "L’aggiornamento è stato interrotto. Controlla la versione installata prima di riprovare."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Installazione non riuscita. Consulta il registro di installazione per i dettagli."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Impossibile leggere l’avanzamento dell’aggiornamento. Riconnessione..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Impossibile avviare l’aggiornamento. Cerca di nuovo gli aggiornamenti e riprova."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Aggiornare Argon alla versione %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Il tema verrà aggiornato con il gestore di pacchetti del sistema. Le impostazioni di Argon saranno mantenute."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Annulla"
|
||||
@@ -380,3 +380,155 @@ msgstr "[ダークモード] 透明度"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "有効な 16 進数のカラーコード"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "リリースノート"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "リリースを表示"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "パッケージをダウンロード"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "更新を確認"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "現在のバージョン"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "最新の安定版"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "不明なバージョン"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "まだ確認していません。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "更新を確認しています..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "前回の確認:%s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "このバージョンのリリースノートはありません。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "更新を確認できません。ルーターと GitHub の接続を確認して、もう一度お試しください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "このバージョンを比較できません。詳しくはリリースをご覧ください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "更新があります。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "テーマは最新です。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "インストール済みのバージョンは、最新の安定版より新しいものです。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "テーマの更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "今すぐ更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "ページを再読み込み"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "自動インストールを利用できません。パッケージをダウンロードして手動で更新してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "インストールログ"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "更新を準備中..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "更新をダウンロード中..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "パッケージを検証中..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "更新をインストール中です。お待ちください..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "更新をインストールしました。ページを再読み込みして新しいバージョンを使用してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "ダウンロードに失敗しました。ルーターから GitHub への接続を確認して再試行してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "パッケージの検証に失敗しました。更新を再確認して再試行してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "更新のインストールに必要な空き容量が不足しています。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "インストール済みのバージョンが変わりました。更新を再確認してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "リリース情報が変更されたか、有効期限が切れています。更新を再確認してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "更新が中断されました。再試行する前にインストール済みのバージョンを確認してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "インストールに失敗しました。詳細はインストールログを確認してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "更新の進行状況を取得できません。再接続中..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "更新を開始できません。更新を再確認して再試行してください。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Argon を %s に更新しますか?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "システムのパッケージマネージャーでテーマを更新します。現在の Argon 設定は保持されます。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
@@ -380,3 +380,155 @@ msgstr "[다크 모드] 투명도"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "유효한 16진수 색상 값"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "릴리스 노트"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "릴리스 보기"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "패키지 다운로드"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "업데이트 확인"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "현재 버전"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "최신 안정 버전"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "알 수 없는 버전"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "아직 확인하지 않았습니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "업데이트 확인 중..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "마지막 확인: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "이 버전에는 릴리스 노트가 없습니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "업데이트를 확인할 수 없습니다. 라우터의 GitHub 연결을 확인한 후 다시 시도하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "이 버전을 비교할 수 없습니다. 자세한 내용은 릴리스를 확인하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "업데이트가 있습니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "테마가 최신 버전입니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "설치된 버전이 최신 안정 버전보다 새 버전입니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "테마 업데이트"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "지금 업데이트"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "페이지 새로고침"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "자동 설치를 사용할 수 없습니다. 패키지를 다운로드하여 수동으로 업데이트하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "설치 로그"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "업데이트 준비 중..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "업데이트 다운로드 중..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "패키지 검증 중..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "업데이트 설치 중입니다. 잠시 기다려 주세요..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "업데이트가 설치되었습니다. 새 버전을 사용하려면 페이지를 새로고침하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "다운로드에 실패했습니다. 라우터의 GitHub 연결을 확인하고 다시 시도하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "패키지 검증에 실패했습니다. 업데이트를 다시 확인하고 시도하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "업데이트를 설치할 여유 공간이 부족합니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "설치된 버전이 변경되었습니다. 업데이트를 다시 확인하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "릴리스 정보가 변경되었거나 만료되었습니다. 업데이트를 다시 확인하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "업데이트가 중단되었습니다. 다시 시도하기 전에 설치된 버전을 확인하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "설치에 실패했습니다. 자세한 내용은 설치 로그를 확인하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "업데이트 진행 상황을 읽을 수 없습니다. 다시 연결 중..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "업데이트를 시작할 수 없습니다. 업데이트를 다시 확인하고 시도하세요."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Argon을 %s 버전으로 업데이트할까요?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "시스템 패키지 관리자로 테마를 업데이트합니다. 현재 Argon 설정은 유지됩니다."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Donkere modus] Transparantie"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "een geldige HEX-kleurwaarde"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Uitgaveopmerkingen"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Uitgave bekijken"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Pakket downloaden"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Op updates controleren"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Huidige versie"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Nieuwste stabiele versie"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Onbekende versie"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Nog niet gecontroleerd."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Controleren op updates..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Laatst gecontroleerd: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Er zijn geen opmerkingen voor deze uitgave gepubliceerd."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Kan niet op updates controleren. Controleer de verbinding van de router met GitHub en probeer het opnieuw."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Deze versie kan niet worden vergeleken. Bekijk de uitgave voor meer informatie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Er is een update beschikbaar."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Uw thema is bijgewerkt."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "De geïnstalleerde versie is nieuwer dan de nieuwste stabiele uitgave."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Thema-updates"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Nu bijwerken"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Pagina herladen"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Automatische installatie is niet beschikbaar. Download het pakket om handmatig bij te werken."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Installatielogboek"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Update voorbereiden..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Update downloaden..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Pakket controleren..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Update installeren. Een ogenblik geduld..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Update geïnstalleerd. Herlaad de pagina om de nieuwe versie te gebruiken."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Download mislukt. Controleer de verbinding van de router met GitHub en probeer het opnieuw."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Pakketcontrole mislukt. Controleer opnieuw op updates en probeer het nogmaals."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Onvoldoende vrije ruimte om de update te installeren."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "De geïnstalleerde versie is gewijzigd. Controleer opnieuw op updates."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "De versiegegevens zijn gewijzigd of verlopen. Controleer opnieuw op updates."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "De update is onderbroken. Controleer de geïnstalleerde versie voordat u het opnieuw probeert."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Installatie mislukt. Raadpleeg het installatielogboek voor meer informatie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Kan de voortgang niet lezen. Opnieuw verbinden..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Kan de update niet starten. Controleer opnieuw op updates en probeer het nogmaals."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Argon bijwerken naar %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Het thema wordt bijgewerkt met de pakketbeheerder van het systeem. Uw Argon-instellingen blijven behouden."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Annuleren"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Ciemny motyw] Przezroczystość"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "prawidłowy kolor w formacie HEX"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Informacje o wydaniu"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Zobacz wydanie"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Pobierz pakiet"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Sprawdź aktualizacje"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Bieżąca wersja"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Najnowsza wersja stabilna"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Nieznana wersja"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Jeszcze nie sprawdzono."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Sprawdzanie aktualizacji..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Ostatnio sprawdzono: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Nie opublikowano informacji o tym wydaniu."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Nie można sprawdzić aktualizacji. Sprawdź połączenie routera z GitHub i spróbuj ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Nie można porównać tej wersji. Szczegóły znajdziesz na stronie wydania."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Dostępna jest aktualizacja."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Motyw jest aktualny."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Zainstalowana wersja jest nowsza od najnowszego wydania stabilnego."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Aktualizacje motywu"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Aktualizuj teraz"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Odśwież stronę"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Automatyczna instalacja jest niedostępna. Pobierz pakiet i zaktualizuj ręcznie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Dziennik instalacji"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Przygotowywanie aktualizacji..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Pobieranie aktualizacji..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Weryfikowanie pakietu..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Instalowanie aktualizacji. Proszę czekać..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Aktualizacja zainstalowana. Odśwież stronę, aby korzystać z nowej wersji."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Pobieranie nie powiodło się. Sprawdź połączenie routera z GitHub i spróbuj ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Weryfikacja pakietu nie powiodła się. Sprawdź aktualizacje i spróbuj ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Za mało wolnego miejsca na instalację aktualizacji."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Zainstalowana wersja uległa zmianie. Sprawdź aktualizacje ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Informacje o wersji uległy zmianie lub wygasły. Sprawdź aktualizacje ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Aktualizacja została przerwana. Przed ponowną próbą sprawdź zainstalowaną wersję."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Instalacja nie powiodła się. Szczegóły znajdziesz w dzienniku instalacji."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Nie można odczytać postępu aktualizacji. Ponowne łączenie..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Nie można rozpocząć aktualizacji. Sprawdź aktualizacje i spróbuj ponownie."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Zaktualizować Argon do %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Motyw zostanie zaktualizowany przy użyciu systemowego menedżera pakietów. Ustawienia Argon zostaną zachowane."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Anuluj"
|
||||
@@ -382,3 +382,155 @@ msgstr "[Modo escuro] Transparência"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "um valor de cor HEX válido"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Notas da versão"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Ver lançamento"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Baixar pacote"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Verificar atualizações"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Versão atual"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Última versão estável"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Versão desconhecida"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Ainda não verificado."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Verificando atualizações..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Última verificação: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Não foram publicadas notas para esta versão."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Não foi possível verificar atualizações. Verifique a conexão do roteador com o GitHub e tente novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Não foi possível comparar esta versão. Consulte o lançamento para mais detalhes."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Há uma atualização disponível."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Seu tema está atualizado."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "A versão instalada é mais recente que a última versão estável."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Atualizações do tema"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Atualizar agora"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Recarregar página"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "A instalação automática não está disponível. Baixe o pacote para atualizar manualmente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Registro de instalação"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Preparando a atualização..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Baixando a atualização..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Verificando o pacote..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Instalando a atualização. Aguarde..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Atualização instalada. Recarregue a página para usar a nova versão."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Falha no download. Verifique a conexão do roteador com o GitHub e tente novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Falha na verificação do pacote. Verifique as atualizações e tente novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Não há espaço livre suficiente para instalar a atualização."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "A versão instalada mudou. Verifique as atualizações novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "As informações da versão mudaram ou expiraram. Verifique as atualizações novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "A atualização foi interrompida. Confira a versão instalada antes de tentar novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Falha na instalação. Consulte o registro de instalação para mais detalhes."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Não foi possível ler o progresso da atualização. Reconectando..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Não foi possível iniciar a atualização. Verifique as atualizações e tente novamente."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Atualizar o Argon para %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "O tema será atualizado com o gerenciador de pacotes do sistema. Suas configurações do Argon serão preservadas."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Тёмная тема] Прозрачность"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "корректное значение HEX-цвета"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Примечания к выпуску"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Открыть выпуск"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Скачать пакет"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Проверить обновления"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Текущая версия"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Последняя стабильная версия"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Неизвестная версия"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Проверка ещё не выполнялась."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Проверка обновлений..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Последняя проверка: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Примечания к этому выпуску не опубликованы."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Не удалось проверить обновления. Проверьте подключение маршрутизатора к GitHub и повторите попытку."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Не удалось сравнить эту версию. Подробности доступны на странице выпуска."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Доступно обновление."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Тема обновлена до последней версии."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Установленная версия новее последнего стабильного выпуска."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Обновления темы"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Обновить сейчас"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Перезагрузить страницу"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Автоматическая установка недоступна. Скачайте пакет для обновления вручную."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Журнал установки"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Подготовка обновления..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Загрузка обновления..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Проверка пакета..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Установка обновления. Подождите..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Обновление установлено. Перезагрузите страницу, чтобы использовать новую версию."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Ошибка загрузки. Проверьте подключение маршрутизатора к GitHub и повторите попытку."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Проверка пакета не пройдена. Проверьте обновления и повторите попытку."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Недостаточно свободного места для установки обновления."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Установленная версия изменилась. Проверьте обновления ещё раз."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Сведения о выпуске изменились или устарели. Проверьте обновления ещё раз."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Обновление прервано. Перед повторной попыткой проверьте установленную версию."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Ошибка установки. Подробности доступны в журнале установки."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Не удалось прочитать ход обновления. Повторное подключение..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Не удалось начать обновление. Проверьте обновления и повторите попытку."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Обновить Argon до %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Тема будет обновлена системным менеджером пакетов. Ваши настройки Argon будут сохранены."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
@@ -387,3 +387,155 @@ msgstr ""
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr ""
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -380,3 +380,155 @@ msgstr "[Koyu mod] Saydamlık"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "geçerli bir HEX renk değeri"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Sürüm notları"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Sürümü görüntüle"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Paketi indir"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Güncellemeleri denetle"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Mevcut sürüm"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "En son kararlı sürüm"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Bilinmeyen sürüm"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Henüz denetlenmedi."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Güncellemeler denetleniyor..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Son denetim: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Bu sürüm için sürüm notları yayımlanmadı."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Güncellemeler denetlenemedi. Yönlendiricinin GitHub bağlantısını kontrol edip yeniden deneyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Bu sürüm karşılaştırılamadı. Ayrıntılar için sürüm sayfasını görüntüleyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Güncelleme mevcut."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Temanız güncel."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Yüklü sürüm, en son kararlı sürümden daha yeni."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Tema güncellemeleri"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Şimdi güncelle"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Sayfayı yeniden yükle"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Otomatik kurulum kullanılamıyor. Elle güncellemek için paketi indirin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Kurulum günlüğü"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Güncelleme hazırlanıyor..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Güncelleme indiriliyor..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Paket doğrulanıyor..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Güncelleme kuruluyor. Lütfen bekleyin..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Güncelleme kuruldu. Yeni sürümü kullanmak için sayfayı yeniden yükleyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "İndirme başarısız. Yönlendiricinin GitHub bağlantısını kontrol edip yeniden deneyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Paket doğrulaması başarısız. Güncellemeleri yeniden denetleyip tekrar deneyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Güncellemeyi kurmak için yeterli boş alan yok."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Yüklü sürüm değişti. Güncellemeleri yeniden denetleyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Sürüm bilgileri değişti veya süresi doldu. Güncellemeleri yeniden denetleyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Güncelleme kesintiye uğradı. Yeniden denemeden önce yüklü sürümü kontrol edin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Kurulum başarısız. Ayrıntılar için kurulum günlüğüne bakın."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Güncelleme ilerlemesi okunamıyor. Yeniden bağlanılıyor..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Güncelleme başlatılamadı. Güncellemeleri yeniden denetleyip tekrar deneyin."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Argon, %s sürümüne güncellensin mi?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Tema, sistemin paket yöneticisiyle güncellenecek. Argon ayarlarınız korunacak."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "İptal"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Темний режим] Прозорість"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "коректне значення кольору у форматі HEX"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Примітки до випуску"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Відкрити випуск"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Завантажити пакунок"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Перевірити оновлення"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Поточна версія"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Остання стабільна версія"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Невідома версія"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Перевірку ще не виконано."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Перевірка оновлень..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Остання перевірка: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Примітки до цього випуску не опубліковані."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Не вдалося перевірити оновлення. Перевірте з’єднання маршрутизатора з GitHub і повторіть спробу."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Не вдалося порівняти цю версію. Докладніше на сторінці випуску."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Доступне оновлення."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Тему оновлено до останньої версії."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Встановлена версія новіша за останній стабільний випуск."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Оновлення теми"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Оновити зараз"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Перезавантажити сторінку"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Автоматичне встановлення недоступне. Завантажте пакунок для оновлення вручну."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Журнал встановлення"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Підготовка оновлення..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Завантаження оновлення..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Перевірка пакунка..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Встановлення оновлення. Зачекайте..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Оновлення встановлено. Перезавантажте сторінку, щоб використовувати нову версію."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Помилка завантаження. Перевірте з’єднання маршрутизатора з GitHub і повторіть спробу."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Перевірку пакунка не пройдено. Перевірте оновлення та повторіть спробу."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Недостатньо вільного місця для встановлення оновлення."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Встановлена версія змінилася. Перевірте оновлення ще раз."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Відомості про випуск змінилися або застаріли. Перевірте оновлення ще раз."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Оновлення перервано. Перед повторною спробою перевірте встановлену версію."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Помилка встановлення. Докладніше в журналі встановлення."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Не вдалося прочитати перебіг оновлення. Повторне підключення..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Не вдалося почати оновлення. Перевірте оновлення та повторіть спробу."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Оновити Argon до %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Тему буде оновлено системним менеджером пакунків. Ваші налаштування Argon буде збережено."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Скасувати"
|
||||
@@ -380,3 +380,155 @@ msgstr "[Chế độ tối] Độ trong suốt"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "mã màu HEX hợp lệ"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "Ghi chú phát hành"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "Xem bản phát hành"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "Tải gói"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "Kiểm tra cập nhật"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "Phiên bản hiện tại"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "Phiên bản ổn định mới nhất"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "Phiên bản không xác định"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "Chưa kiểm tra."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "Đang kiểm tra cập nhật..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "Lần kiểm tra gần nhất: %s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "Không có ghi chú cho bản phát hành này."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "Không thể kiểm tra cập nhật. Hãy kiểm tra kết nối của bộ định tuyến tới GitHub rồi thử lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "Không thể so sánh phiên bản này. Xem bản phát hành để biết chi tiết."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "Có bản cập nhật."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "Giao diện đã được cập nhật."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "Phiên bản đã cài đặt mới hơn bản ổn định mới nhất."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "Cập nhật giao diện"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "Cập nhật ngay"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "Tải lại trang"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "Không thể cài đặt tự động. Hãy tải gói để cập nhật thủ công."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "Nhật ký cài đặt"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "Đang chuẩn bị cập nhật..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "Đang tải bản cập nhật..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "Đang xác minh gói..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "Đang cài đặt bản cập nhật. Vui lòng đợi..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "Đã cài đặt bản cập nhật. Hãy tải lại trang để dùng phiên bản mới."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "Tải xuống thất bại. Hãy kiểm tra kết nối của bộ định tuyến tới GitHub rồi thử lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "Xác minh gói thất bại. Hãy kiểm tra cập nhật rồi thử lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "Không đủ dung lượng trống để cài đặt bản cập nhật."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "Phiên bản đã cài đặt đã thay đổi. Hãy kiểm tra cập nhật lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "Thông tin phiên bản đã thay đổi hoặc hết hạn. Hãy kiểm tra cập nhật lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "Cập nhật đã bị gián đoạn. Hãy kiểm tra phiên bản đã cài trước khi thử lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "Cài đặt thất bại. Xem nhật ký cài đặt để biết chi tiết."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "Không thể đọc tiến trình cập nhật. Đang kết nối lại..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "Không thể bắt đầu cập nhật. Hãy kiểm tra cập nhật rồi thử lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "Cập nhật Argon lên %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "Giao diện sẽ được cập nhật bằng trình quản lý gói hệ thống. Cấu hình Argon của bạn sẽ được giữ lại."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "Hủy"
|
||||
@@ -382,3 +382,155 @@ msgstr "[暗色模式] 透明度"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "有效的十六进制颜色值"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "更新日志"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "查看发布页"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "下载安装包"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "检查更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "当前版本"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "最新稳定版"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "未知版本"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "尚未检查。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "正在检查更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "上次检查:%s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "此版本未提供更新日志。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "检查更新失败。请检查路由器与 GitHub 的连接后重试。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "无法比较此版本。请查看发布页了解详情。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "有可用更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "主题已是最新版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "本地安装版本高于最新稳定版。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "主题更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "立即更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "重新加载页面"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "暂时无法自动安装。请下载安装包手动更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "安装日志"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "正在准备更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "正在下载更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "正在校验安装包..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "正在安装更新,请稍候..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "更新已安装。请重新加载页面以使用新版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "下载失败。请检查路由器与 GitHub 的连接后重试。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "安装包校验失败。请重新检查更新后重试。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "可用空间不足,无法安装更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "已安装版本发生变化。请重新检查更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "版本信息已变化或过期。请重新检查更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "更新已中断。重试前请检查已安装的版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "安装失败。请查看安装日志了解详情。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "无法读取更新进度,正在重新连接..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "无法开始更新。请重新检查更新后重试。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "将 Argon 更新到 %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "将使用系统包管理器更新主题,并保留当前 Argon 配置。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
@@ -382,3 +382,155 @@ msgstr "[深色模式] 透明度"
|
||||
#: htdocs/luci-static/resources/view/argon-config.js:47
|
||||
msgid "valid HEX color value"
|
||||
msgstr "有效的十六進制顏色值"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release notes"
|
||||
msgstr "更新日誌"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "View release"
|
||||
msgstr "查看發佈頁"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download package"
|
||||
msgstr "下載安裝套件"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Check for updates"
|
||||
msgstr "檢查更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Current version"
|
||||
msgstr "目前版本"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Latest stable version"
|
||||
msgstr "最新穩定版"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unknown version"
|
||||
msgstr "未知版本"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not checked yet."
|
||||
msgstr "尚未檢查。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Checking for updates..."
|
||||
msgstr "正在檢查更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Last checked: %s"
|
||||
msgstr "上次檢查:%s"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "No release notes were published."
|
||||
msgstr "此版本未提供更新日誌。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to check for updates. Check the router's connection to GitHub and try again."
|
||||
msgstr "檢查更新失敗。請檢查路由器與 GitHub 的連線後重試。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to compare this version. View the release for details."
|
||||
msgstr "無法比較此版本。請查看發佈頁以瞭解詳情。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update available."
|
||||
msgstr "有可用更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Your theme is up to date."
|
||||
msgstr "佈景主題已是最新版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version is newer than the latest stable release."
|
||||
msgstr "本機安裝版本高於最新穩定版。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Theme updates"
|
||||
msgstr "佈景主題更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update now"
|
||||
msgstr "立即更新"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Reload page"
|
||||
msgstr "重新載入頁面"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Automatic installation is unavailable. Download the package to update manually."
|
||||
msgstr "暫時無法自動安裝。請下載安裝套件手動更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation log"
|
||||
msgstr "安裝日誌"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Preparing the update..."
|
||||
msgstr "正在準備更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Downloading the update..."
|
||||
msgstr "正在下載更新..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Verifying the package..."
|
||||
msgstr "正在驗證安裝套件..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installing the update. Please wait..."
|
||||
msgstr "正在安裝更新,請稍候..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update installed. Reload the page to use the new version."
|
||||
msgstr "更新已安裝。請重新載入頁面以使用新版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Download failed. Check the router's connection to GitHub and try again."
|
||||
msgstr "下載失敗。請檢查路由器與 GitHub 的連線後重試。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Package verification failed. Check for updates and try again."
|
||||
msgstr "安裝套件驗證失敗。請重新檢查更新後重試。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Not enough free space to install the update."
|
||||
msgstr "可用空間不足,無法安裝更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The installed version has changed. Check for updates again."
|
||||
msgstr "已安裝版本發生變化。請重新檢查更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Release information has changed or expired. Check for updates again."
|
||||
msgstr "版本資訊已變更或過期。請重新檢查更新。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The update was interrupted. Check the installed version before trying again."
|
||||
msgstr "更新已中斷。重試前請檢查已安裝的版本。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Installation failed. See the installation log for details."
|
||||
msgstr "安裝失敗。請查看安裝日誌瞭解詳情。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to read update progress. Reconnecting..."
|
||||
msgstr "無法讀取更新進度,正在重新連線..."
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Unable to start the update. Check for updates and try again."
|
||||
msgstr "無法開始更新。請重新檢查更新後重試。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Update Argon to %s?"
|
||||
msgstr "將 Argon 更新至 %s?"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "The theme will be updated using the system package manager. Your Argon settings will be preserved."
|
||||
msgstr "將使用系統套件管理器更新佈景主題,並保留目前的 Argon 設定。"
|
||||
|
||||
#: htdocs/luci-static/resources/argon/updates.js
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
+351
@@ -0,0 +1,351 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
readonly state_dir='/var/run/argon-update'
|
||||
readonly cache_file='/var/run/argon-update/release.json'
|
||||
readonly release_api='https://api.github.com/repos/jerrykuku/luci-theme-argon/releases/latest'
|
||||
|
||||
installed_version() {
|
||||
current_version=''
|
||||
package_manager=''
|
||||
if command -v apk >/dev/null 2>&1; then
|
||||
current_version="$(apk list --installed luci-theme-argon 2>/dev/null |
|
||||
awk '$1 ~ /^luci-theme-argon-/ { sub(/^luci-theme-argon-/, "", $1); print $1; exit }')"
|
||||
[ -z "$current_version" ] || package_manager=apk
|
||||
fi
|
||||
if [ -z "$current_version" ] && command -v opkg >/dev/null 2>&1; then
|
||||
current_version="$(opkg status luci-theme-argon 2>/dev/null | awk '
|
||||
/^Version: / { version=$2 }
|
||||
/^Status: .* installed$/ { installed=1 }
|
||||
END { if (installed) print version }')"
|
||||
[ -z "$current_version" ] || package_manager=opkg
|
||||
fi
|
||||
}
|
||||
|
||||
valid_tag() {
|
||||
[ "${#1}" -le 48 ] && printf '%s\n' "$1" | grep -Eq '^v?[0-9]+(\.[0-9]+){1,3}$'
|
||||
}
|
||||
|
||||
read_cache() {
|
||||
[ -f "$cache_file" ] && [ ! -L "$cache_file" ] &&
|
||||
[ "$(wc -c < "$cache_file")" -le 1048576 ] || return 1
|
||||
json_load_file "$cache_file" || return 1
|
||||
json_get_var tag tag
|
||||
json_get_var checked_at checked_at
|
||||
valid_tag "$tag" && printf '%s\n' "$checked_at" | grep -Eq '^[0-9]{1,11}$'
|
||||
}
|
||||
|
||||
select_package() {
|
||||
case "$package_manager" in apk) format=apk ;; opkg) format=ipk ;; *) return 1 ;; esac
|
||||
json_get_var package "$format"
|
||||
json_get_var digest "${format}_sha256"
|
||||
json_get_var size "${format}_size"
|
||||
json_get_var tag tag
|
||||
valid_tag "$tag" || return 1
|
||||
base="${tag#v}"
|
||||
case "$package_manager:$package" in
|
||||
apk:luci-theme-argon-"$base"-r*.apk)
|
||||
target_version="${package#luci-theme-argon-}"
|
||||
target_version="${target_version%.apk}"
|
||||
revision="${target_version#"$base"-r}" ;;
|
||||
opkg:luci-theme-argon_"$base"*_all.ipk)
|
||||
target_version="${package#luci-theme-argon_}"
|
||||
target_version="${target_version%_all.ipk}"
|
||||
case "$target_version" in "$base") revision=1 ;; "$base"-*) revision="${target_version#"$base"-}" ;; *) return 1 ;; esac ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
printf '%s\n' "$revision" | grep -Eq '^[0-9]{1,8}$' &&
|
||||
printf '%s\n' "$digest" | grep -Eq '^[a-f0-9]{64}$' &&
|
||||
printf '%s\n' "$size" | grep -Eq '^[0-9]{1,8}$' &&
|
||||
[ "$size" -gt 0 ] && [ "$size" -le 8388608 ]
|
||||
}
|
||||
|
||||
is_upgrade() {
|
||||
# Reject unknown/custom version syntax before asking the native comparator.
|
||||
printf '%s\n' "$current_version" | grep -Eq '^[0-9]+(\.[0-9]+){1,3}((~|_)(alpha|beta|rc)[0-9]+|-(alpha|beta|rc)\.[0-9]+)?(-r?[0-9]+)?$' || return 1
|
||||
case "$package_manager" in
|
||||
apk) [ "$(apk version -t "$current_version" "$target_version" 2>/dev/null)" = '<' ] ;;
|
||||
opkg) opkg compare-versions "$current_version" '<<' "$target_version" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
prepare_state() {
|
||||
[ ! -L "$state_dir" ] && { [ -d "$state_dir" ] || mkdir -m 700 "$state_dir"; } &&
|
||||
command -v flock >/dev/null 2>&1 && command -v sha256sum >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1
|
||||
}
|
||||
|
||||
add_status() {
|
||||
# Keep release data in the caller's namespace while loading the small job file.
|
||||
json_set_namespace upgrade_status previous_namespace
|
||||
json_init
|
||||
phase=idle
|
||||
job_error=''
|
||||
job_version=''
|
||||
if [ -f "$state_dir/status.json" ] && [ ! -L "$state_dir/status.json" ] &&
|
||||
[ "$(wc -c < "$state_dir/status.json")" -le 4096 ] && json_load_file "$state_dir/status.json"; then
|
||||
json_get_var phase phase
|
||||
json_get_var job_error error
|
||||
json_get_var job_version version
|
||||
fi
|
||||
active=0
|
||||
case "$phase" in
|
||||
starting|downloading|verifying|installing)
|
||||
# A kernel lock survives the initiating RPC and is released on worker exit.
|
||||
if command -v flock >/dev/null 2>&1; then
|
||||
exec 8>"$state_dir/lock"
|
||||
if flock -n 8; then
|
||||
# The worker may have finished between our snapshot and lock probe.
|
||||
# Read its final state while holding the lock against a new start.
|
||||
json_load_file "$state_dir/status.json"
|
||||
json_get_var phase phase
|
||||
json_get_var job_error error
|
||||
json_get_var job_version version
|
||||
case "$phase" in starting|downloading|verifying|installing) phase=failed; job_error=interrupted ;; esac
|
||||
else
|
||||
active=1
|
||||
fi
|
||||
exec 8>&-
|
||||
else
|
||||
phase=failed
|
||||
job_error=interrupted
|
||||
fi ;;
|
||||
esac
|
||||
json_set_namespace "$previous_namespace"
|
||||
json_add_object upgrade
|
||||
json_add_string phase "$phase"
|
||||
json_add_string error "$job_error"
|
||||
json_add_string version "$job_version"
|
||||
json_add_boolean active "$active"
|
||||
if [ -f "$state_dir/log" ] && [ ! -L "$state_dir/log" ]; then
|
||||
json_add_string log "$(tail -c 8192 "$state_dir/log")"
|
||||
fi
|
||||
json_close_object
|
||||
}
|
||||
|
||||
respond() {
|
||||
add_status
|
||||
# Read after the job snapshot so a completed job reports its installed version.
|
||||
installed_version
|
||||
can_upgrade=0
|
||||
if select_package && is_upgrade && command -v flock >/dev/null 2>&1 && command -v sha256sum >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1; then
|
||||
can_upgrade=1
|
||||
fi
|
||||
json_add_int result "$1"
|
||||
json_add_string current_version "$current_version"
|
||||
json_add_string package_manager "$package_manager"
|
||||
json_add_boolean can_upgrade "$can_upgrade"
|
||||
json_dump
|
||||
}
|
||||
|
||||
fail() {
|
||||
json_init
|
||||
respond "$1"
|
||||
}
|
||||
|
||||
write_status() {
|
||||
json_init
|
||||
json_add_string phase "$1"
|
||||
json_add_string error "${2:-}"
|
||||
json_add_string version "$target_version"
|
||||
json_dump > "$state_dir/status.$$" && mv -f "$state_dir/status.$$" "$state_dir/status.json"
|
||||
}
|
||||
|
||||
run_upgrade() {
|
||||
# Run a private copy, since installing the theme replaces this RPC script.
|
||||
work="${0%/*}"
|
||||
case "$work" in "$state_dir"/job.??????) ;; *) return 1 ;; esac
|
||||
[ -d "$work" ] && [ ! -L "$work" ] && [ -f "$work/release.json" ] || return 1
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
trap 'write_status failed interrupted; exit 1' INT TERM
|
||||
json_load_file "$work/release.json" && select_package || { write_status failed metadata; return; }
|
||||
installed_version
|
||||
is_upgrade || { write_status failed version; return; }
|
||||
# Leave room for download metadata and unpacking. The package manager also
|
||||
# performs its own dependency and storage checks; never force those checks.
|
||||
tmp_free="$(df -Pk "$state_dir" | awk 'END { print $4 }')"
|
||||
root_path=/
|
||||
[ ! -d /overlay ] || root_path=/overlay
|
||||
root_free="$(df -Pk "$root_path" | awk 'END { print $4 }')"
|
||||
if [ "${tmp_free:-0}" -lt "$((size / 1024 + 2048))" ] ||
|
||||
[ "${root_free:-0}" -lt "$((size * 3 / 1024 + 1024))" ]; then
|
||||
write_status failed space
|
||||
return
|
||||
fi
|
||||
write_status downloading
|
||||
url="https://github.com/jerrykuku/luci-theme-argon/releases/download/$tag/$package"
|
||||
(ulimit -f 16384; timeout -k 2 90 wget -T 20 -q -U 'luci-theme-argon' \
|
||||
-O "$work/$package" "$url") 2>/dev/null || { write_status failed network; return; }
|
||||
write_status verifying
|
||||
if [ "$(wc -c < "$work/$package")" -ne "$size" ] ||
|
||||
[ "$(sha256sum "$work/$package" | awk '{ print $1 }')" != "$digest" ]; then
|
||||
write_status failed checksum
|
||||
return
|
||||
fi
|
||||
# Recheck immediately before modifying the package database.
|
||||
installed_version
|
||||
is_upgrade || { write_status failed version; return; }
|
||||
write_status installing
|
||||
# Bound captured output without imposing a file-size limit on the installer.
|
||||
(
|
||||
case "$package_manager" in
|
||||
apk) apk add --allow-untrusted "$work/$package" ;;
|
||||
opkg) opkg install "$work/$package" ;;
|
||||
esac
|
||||
printf '%s\n' "$?" > "$work/exit"
|
||||
) 2>&1 | tail -c 8192 > "$state_dir/log"
|
||||
if [ "$(cat "$work/exit" 2>/dev/null)" != 0 ]; then
|
||||
write_status failed install
|
||||
return
|
||||
fi
|
||||
installed_version
|
||||
if [ "$current_version" != "$target_version" ]; then
|
||||
write_status failed install
|
||||
return
|
||||
fi
|
||||
write_status complete
|
||||
}
|
||||
|
||||
start_upgrade() {
|
||||
read -r request
|
||||
json_load "$request" || { fail 3; return; }
|
||||
json_get_var requested_tag tag
|
||||
json_get_var requested_package package
|
||||
now="$(date +%s)"
|
||||
read_cache && [ "$now" -ge "$checked_at" ] && [ "$((now - checked_at))" -lt 300 ] &&
|
||||
select_package && [ "$tag" = "$requested_tag" ] && [ "$package" = "$requested_package" ] || { fail 3; return; }
|
||||
is_upgrade || { fail 5; return; }
|
||||
prepare_state || { fail 1; return; }
|
||||
exec 9>"$state_dir/lock"
|
||||
flock -n 9 || { fail 4; return; }
|
||||
work="$(mktemp -d "$state_dir/job.XXXXXX")" || { fail 1; return; }
|
||||
if ! cp "$0" "$work/worker.sh" || ! json_dump > "$work/release.json"; then
|
||||
rm -rf "$work"
|
||||
fail 1
|
||||
return
|
||||
fi
|
||||
: > "$state_dir/log"
|
||||
write_status starting
|
||||
# FD 9 is inherited by the worker, keeping the lock until all installation
|
||||
# work finishes. Detach every stdio stream so rpcd can reply immediately.
|
||||
(trap '' HUP; exec sh "$work/worker.sh" run "$package_manager") </dev/null >/dev/null 2>&1 &
|
||||
json_init
|
||||
respond 0
|
||||
}
|
||||
|
||||
umask 077
|
||||
case "$1" in
|
||||
list)
|
||||
printf '%s\n' '{"get":{},"check":{},"status":{},"start":{"tag":"String","package":"String"}}'
|
||||
;;
|
||||
run)
|
||||
package_manager="$2"
|
||||
run_upgrade
|
||||
;;
|
||||
call)
|
||||
case "$2" in get|check|status|start) ;; *) exit 1 ;; esac
|
||||
if [ "$2" = status ]; then
|
||||
json_init
|
||||
respond 0
|
||||
exit 0
|
||||
fi
|
||||
if [ "$2" = start ]; then
|
||||
installed_version
|
||||
start_upgrade
|
||||
exit 0
|
||||
fi
|
||||
if [ "$2" = get ]; then
|
||||
read_cache || json_init
|
||||
respond 0
|
||||
exit 0
|
||||
fi
|
||||
now="$(date +%s)"
|
||||
if read_cache && [ "$now" -ge "$checked_at" ] && [ "$((now - checked_at))" -lt 300 ]; then
|
||||
respond 0
|
||||
exit 0
|
||||
fi
|
||||
[ -L "$state_dir" ] || [ -d "$state_dir" ] || mkdir -m 700 "$state_dir" 2>/dev/null || :
|
||||
umask 077
|
||||
work="$(mktemp -d /tmp/argon-update.XXXXXX)" || { fail 1; exit 0; }
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
trap 'exit 1' HUP INT TERM
|
||||
# Bound the request to less than rpcd's timeout and limit the response size.
|
||||
(ulimit -f 2048; timeout -k 2 12 wget -T 10 -q -U 'luci-theme-argon' \
|
||||
--header='Accept: application/vnd.github+json' \
|
||||
--header='Cache-Control: no-cache' \
|
||||
-O "$work/release.json" "$release_api") 2>/dev/null || { fail 1; exit 0; }
|
||||
[ "$(wc -c < "$work/release.json")" -le 1048576 ] &&
|
||||
json_load_file "$work/release.json" || { fail 2; exit 0; }
|
||||
json_get_var tag tag_name
|
||||
json_get_var draft draft
|
||||
json_get_var prerelease prerelease
|
||||
valid_tag "$tag" && [ "$draft" = 0 ] && [ "$prerelease" = 0 ] || { fail 2; exit 0; }
|
||||
json_get_var published_at published_at
|
||||
json_get_var notes body
|
||||
base="${tag#v}"
|
||||
ipk=''
|
||||
apk=''
|
||||
ipk_sha256=''
|
||||
apk_sha256=''
|
||||
ipk_size=0
|
||||
apk_size=0
|
||||
ipk_revision=-1
|
||||
apk_revision=-1
|
||||
if json_select assets; then
|
||||
json_get_keys asset_keys
|
||||
for asset_key in $asset_keys; do
|
||||
json_select "$asset_key" || continue
|
||||
json_get_var asset name
|
||||
json_get_var asset_digest digest
|
||||
json_get_var asset_size size
|
||||
# Older releases may not expose a checksum. Keep manual downloads,
|
||||
# but only checksum-backed assets can be installed through this RPC.
|
||||
asset_digest="${asset_digest#sha256:}"
|
||||
printf '%s\n' "$asset_digest" | grep -Eq '^[a-f0-9]{64}$' || asset_digest=''
|
||||
printf '%s\n' "$asset_size" | grep -Eq '^[0-9]{1,8}$' || asset_size=0
|
||||
case "$asset" in
|
||||
"luci-theme-argon_${base}"*_all.ipk)
|
||||
revision="${asset#luci-theme-argon_${base}}"
|
||||
revision="${revision%_all.ipk}"
|
||||
case "$revision" in '') revision=1 ;; -*) revision="${revision#-}" ;; *) revision='' ;; esac
|
||||
if printf '%s\n' "$revision" | grep -Eq '^[0-9]{1,8}$' && [ "$revision" -gt "$ipk_revision" ]; then
|
||||
ipk="$asset"
|
||||
ipk_sha256="$asset_digest"
|
||||
ipk_size="$asset_size"
|
||||
ipk_revision="$revision"
|
||||
fi
|
||||
;;
|
||||
"luci-theme-argon-${base}-r"*.apk)
|
||||
revision="${asset#luci-theme-argon-${base}-r}"
|
||||
revision="${revision%.apk}"
|
||||
if printf '%s\n' "$revision" | grep -Eq '^[0-9]{1,8}$' && [ "$revision" -gt "$apk_revision" ]; then
|
||||
apk="$asset"
|
||||
apk_sha256="$asset_digest"
|
||||
apk_size="$asset_size"
|
||||
apk_revision="$revision"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
json_select ..
|
||||
done
|
||||
fi
|
||||
json_init
|
||||
json_add_string tag "$tag"
|
||||
json_add_string published_at "$published_at"
|
||||
json_add_string notes "$notes"
|
||||
json_add_string ipk "$ipk"
|
||||
json_add_string apk "$apk"
|
||||
json_add_string ipk_sha256 "$ipk_sha256"
|
||||
json_add_string apk_sha256 "$apk_sha256"
|
||||
json_add_int ipk_size "$ipk_size"
|
||||
json_add_int apk_size "$apk_size"
|
||||
json_add_int checked_at "$now"
|
||||
json_dump > "$work/cache.json"
|
||||
# Cache only successful checks, atomically; a failed cache write is nonfatal.
|
||||
if [ ! -L "$cache_file" ] && { [ ! -e "$cache_file" ] || [ -f "$cache_file" ]; }; then
|
||||
mv -f "$work/cache.json" "$cache_file" 2>/dev/null || :
|
||||
fi
|
||||
respond 0
|
||||
;;
|
||||
esac
|
||||
@@ -7,6 +7,7 @@
|
||||
},
|
||||
"ubus": {
|
||||
"luci.argon": [ "avail" ],
|
||||
"luci.argon_update": [ "get", "check", "status" ],
|
||||
"luci.argon_appearance": [ "get" ],
|
||||
"luci.argon_branding": [ "get" ]
|
||||
},
|
||||
@@ -19,6 +20,7 @@
|
||||
},
|
||||
"ubus": {
|
||||
"luci.argon": [ "remove", "rename" ],
|
||||
"luci.argon_update": [ "start" ],
|
||||
"luci.argon_appearance": [ "set" ],
|
||||
"luci.argon_branding": [ "set", "reset" ]
|
||||
},
|
||||
|
||||
@@ -97,11 +97,12 @@ function fixture(options = {}) {
|
||||
};
|
||||
const L = { dom: { callClassMethod(node, method, value) { assert.equal(method, 'setValue'); node.value = value; } }, bind: (fn, context) => fn.bind(context), resolveDefault: (promise, value) => Promise.resolve(promise).catch(() => value), resource: name => '/luci-static/resources/' + name };
|
||||
state.window = new EventTarget();
|
||||
state.view = new Function('form', 'fs', 'rpc', 'uci', 'ui', 'view', 'L', 'E', '_', 'cbi_update_table', 'location', 'document', 'branding', 'window', source)(
|
||||
state.view = new Function('form', 'fs', 'rpc', 'uci', 'ui', 'view', 'L', 'E', '_', 'cbi_update_table', 'location', 'document', 'branding', 'window', 'updates', source)(
|
||||
form, fileApi, rpc, { load: () => Promise.resolve(), get: (config, section, key) => state.settings?.[key] }, ui, { extend: value => value }, L, E,
|
||||
value => value, (table, rows) => { state.rows = rows; }, { reload() { state.reloads++; } },
|
||||
{ getElementById: id => state.nodes[id] },
|
||||
{ load: () => Promise.resolve({ result: 0 }), render: () => E('div', {}, []) }, state.window
|
||||
{ load: () => Promise.resolve({ result: 0 }), render: () => E('div', {}, []) }, state.window,
|
||||
{ load: () => Promise.resolve({ result: 0 }), render: () => E('div', {}, []) }
|
||||
);
|
||||
state.render = async () => state.view.render(await state.view.load());
|
||||
state.button = name => state.map.options.find(option => option.name === name);
|
||||
|
||||
@@ -46,7 +46,7 @@ const env = proto({
|
||||
urlencode: value => replace(replace(replace(value, ' ', '%20'), '#', '%23'), '?', '%3F') },
|
||||
ubus: { call: (object, method) => object == 'luci.argon_wallpaper'
|
||||
? fixture.wallpaper : { hostname: fixture.hostname ?? 'Router' } },
|
||||
ctx: { path: ['admin', 'status', 'overview'], request_path: ['admin', 'status', 'overview'], authsession: 'session' },
|
||||
ctx: fixture.ctx ?? { path: ['admin', 'status', 'overview'], request_path: ['admin', 'status', 'overview'], authsession: 'session' },
|
||||
version: { luciname: 'LuCI', luciversion: 'test-build', distname: 'OpenWrt', distversion: '25.12.5', distrevision: 'test', disturl: 'https://openwrt.org/' },
|
||||
_: value => value, entityencode: encode, striptags: value => replace(value, /<[^>]*>/g, ''),
|
||||
node: fixture.node ?? {}, css: fixture.css, duser: fixture.duser ?? 'root',
|
||||
|
||||
@@ -41,6 +41,22 @@ test('application and login compose the same head with their own resource bounda
|
||||
} finally { renderer.close(); }
|
||||
});
|
||||
|
||||
test('first-child entry routes identify the resolved page and retain wildcard request suffixes', () => {
|
||||
const renderer = createRenderer(templates);
|
||||
try {
|
||||
for (const request_path of [[], ['admin'], ['admin', 'status'], ['admin', 'status', 'overview']]) {
|
||||
const { html } = renderer.render('application', {
|
||||
ctx: { path: ['admin', 'status', 'overview'], request_path, authsession: 'session' }
|
||||
});
|
||||
assert.match(html, /data-page="admin-status-overview"/);
|
||||
}
|
||||
const { html } = renderer.render('application', {
|
||||
ctx: { path: ['admin', 'network', 'network'], request_path: ['admin', 'network', 'network', 'lan'], authsession: 'session' }
|
||||
});
|
||||
assert.match(html, /data-page="admin-network-network-lan"/);
|
||||
} finally { renderer.close(); }
|
||||
});
|
||||
|
||||
test('login partials retain image/video, branding and authentication scope and script order', () => {
|
||||
const renderer = createRenderer(templates);
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
"""Run the real update RPC with isolated package managers, HTTP and cache files."""
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
API = 'https://api.github.com/repos/jerrykuku/luci-theme-argon/releases/latest'
|
||||
|
||||
|
||||
class UpdateRpcTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.directory = Path(self.temp.name)
|
||||
self.cache = self.directory / 'cache.json'
|
||||
self.payload = self.directory / 'release.json'
|
||||
self.requests = self.directory / 'requests'
|
||||
fakebin = self.directory / 'bin'
|
||||
fakebin.mkdir()
|
||||
scripts = {
|
||||
'apk': '''case "$1" in
|
||||
list) test -n "$APK_VERSION" || exit 1; v=$APK_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'luci-theme-argon-%s noarch [installed]\\n' "$v" ;;
|
||||
version) test "$COMPARE_FAIL" != 1 || exit 1; [ "$3" = "$4" ] && printf '=\\n' || { [ "$3" = 3.0.0-r20261015 ] && printf '>\\n' || printf '<\\n'; } ;;
|
||||
add) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-r2' > "$INSTALLED"; echo 'Theme installed' ;;
|
||||
esac
|
||||
''',
|
||||
'opkg': '''case "$1" in
|
||||
status) v=$OPKG_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'Package: luci-theme-argon\\nVersion: %s\\nStatus: install ok installed\\n' "$v" ;;
|
||||
compare-versions) [ "$3" = "<<" ] && [ "$COMPARE_FAIL" != 1 ] && [ "$2" != "$4" ] && [ "$2" != 3.0.0-20261015 ] ;;
|
||||
install) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-2' > "$INSTALLED"; echo 'Theme installed' ;;
|
||||
esac
|
||||
''',
|
||||
'df': 'printf "Filesystem 1024-blocks Used Available Capacity Mounted on\\nroot 100000 1000 %s 1%% /\\n" "${FREE_KB:-99000}"\n',
|
||||
'wget': '''printf '%s\\n' "$@" >> "$REQUESTS"
|
||||
test "$FETCH_FAIL" != 1 || exit 8
|
||||
while [ "$#" -gt 0 ]; do
|
||||
if [ "$1" = -O ]; then shift; destination=$1; fi
|
||||
shift
|
||||
done
|
||||
case "$destination" in
|
||||
*release.json) cp "$PAYLOAD" "$destination" ;;
|
||||
*) sleep "${DOWNLOAD_DELAY:-0}"; test "$DOWNLOAD_FAIL" != 1 || exit 8; cp "$PACKAGE_DATA" "$destination" ;;
|
||||
esac
|
||||
'''
|
||||
}
|
||||
for name, content in scripts.items():
|
||||
path = fakebin / name
|
||||
path.write_text('#!/bin/sh\n' + content)
|
||||
path.chmod(0o755)
|
||||
helper = self.directory / 'json_fixture.py'
|
||||
helper.write_text('''import json,sys
|
||||
root=json.load(sys.stdin); path=json.loads(sys.argv[1]); op=sys.argv[2]; args=sys.argv[3:]
|
||||
obj=root
|
||||
for key in path: obj=obj[int(key)] if isinstance(obj,list) else obj[key]
|
||||
if op=='select':
|
||||
if args[0]=='..': path=path[:-1]
|
||||
else:
|
||||
child=obj[int(args[0])] if isinstance(obj,list) else obj[args[0]]
|
||||
if not isinstance(child,(dict,list)): raise ValueError('not a container')
|
||||
path.append(args[0])
|
||||
print(json.dumps(path))
|
||||
elif op=='keys': print(' '.join(map(str,range(len(obj)) if isinstance(obj,list) else obj.keys())))
|
||||
elif op=='get':
|
||||
value=obj.get(args[0],'')
|
||||
print(int(value) if isinstance(value,bool) else '' if value is None else value)
|
||||
elif op=='add':
|
||||
obj[args[1]]=int(args[2]) if args[0]=='int' else bool(int(args[2])) if args[0]=='boolean' else {} if args[0]=='object' else args[2]
|
||||
print(json.dumps(root))
|
||||
elif op=='validate':
|
||||
if not isinstance(root,(dict,list)): raise ValueError('invalid root')
|
||||
''')
|
||||
shim = self.directory / 'jshn.sh'
|
||||
shim.write_text(f'''fixture_json() {{ printf '%s' "$FIXTURE_JSON" | python3 '{helper}' "$FIXTURE_PATH" "$@"; }}
|
||||
json_load() {{ FIXTURE_JSON=$1; FIXTURE_PATH='[]'; fixture_json validate >/dev/null 2>&1; }}
|
||||
json_load_file() {{ json_load "$(cat "$1")"; }}
|
||||
json_init() {{ FIXTURE_JSON='{{}}'; FIXTURE_PATH='[]'; }}
|
||||
json_get_var() {{ fixture_value=$(fixture_json get "$2"); export "$1=$fixture_value"; }}
|
||||
json_get_keys() {{ fixture_value=$(fixture_json keys); export "$1=$fixture_value"; }}
|
||||
json_select() {{ fixture_value=$(fixture_json select "$1" 2>/dev/null) || return 1; FIXTURE_PATH=$fixture_value; }}
|
||||
json_add_string() {{ FIXTURE_JSON=$(fixture_json add string "$1" "$2"); }}
|
||||
json_add_int() {{ FIXTURE_JSON=$(fixture_json add int "$1" "$2"); }}
|
||||
json_add_boolean() {{ FIXTURE_JSON=$(fixture_json add boolean "$1" "$2"); }}
|
||||
json_add_object() {{ FIXTURE_JSON=$(fixture_json add object "$1" ''); json_select "$1"; }}
|
||||
json_close_object() {{ json_select ..; }}
|
||||
json_set_namespace() {{
|
||||
if [ "$1" = upgrade_status ]; then FIXTURE_SAVED_JSON=$FIXTURE_JSON; FIXTURE_SAVED_PATH=$FIXTURE_PATH; export "$2=base";
|
||||
else FIXTURE_JSON=$FIXTURE_SAVED_JSON; FIXTURE_PATH=$FIXTURE_SAVED_PATH; fi
|
||||
}}
|
||||
|
||||
json_dump() {{ printf '%s\\n' "$FIXTURE_JSON"; }}
|
||||
''')
|
||||
self.script = self.directory / 'rpc.sh'
|
||||
self.script.write_text((ROOT / 'root/usr/libexec/rpcd/luci.argon_update').read_text()
|
||||
.replace('/usr/share/libubox/jshn.sh', str(shim))
|
||||
.replace('/var/run/argon-update/release.json', str(self.cache))
|
||||
.replace('/var/run/argon-update', str(self.directory / 'state')))
|
||||
self.env = dict(os.environ, PATH=str(fakebin) + os.pathsep + os.environ['PATH'],
|
||||
APK_VERSION='3.0.0-r1', OPKG_VERSION='', PAYLOAD=str(self.payload),
|
||||
REQUESTS=str(self.requests), FETCH_FAIL='0', INSTALLED=str(self.directory / 'installed'),
|
||||
MUTATIONS=str(self.directory / 'mutations'), PACKAGE_DATA=str(self.directory / 'package'))
|
||||
(self.directory / 'package').write_bytes(b'argon-package')
|
||||
self.release = {'tag_name': 'v3.0.0', 'draft': False, 'prerelease': False,
|
||||
'published_at': '2026-10-16T01:00:00Z', 'body': '## 更新\n- 修复布局。',
|
||||
'assets': [{'name': name, 'digest': 'sha256:' + hashlib.sha256(b'argon-package').hexdigest(), 'size': 13} for name in [
|
||||
'luci-theme-argon-3.0.0-r1.apk', 'luci-theme-argon_3.0.0_all.ipk',
|
||||
'luci-theme-argon-3.0.0-r2.apk', 'luci-theme-argon_3.0.0-2_all.ipk',
|
||||
'luci-theme-argon-3.0.0-r1.apk', 'luci-theme-argon_3.0.0_all.ipk']]}
|
||||
self.payload.write_text(json.dumps(self.release))
|
||||
|
||||
def call(self, method, **arguments):
|
||||
result = subprocess.run(['sh', str(self.script), 'call', method],
|
||||
input=json.dumps(arguments) + '\n', env=self.env,
|
||||
capture_output=True, text=True, check=True)
|
||||
return json.loads(result.stdout)
|
||||
|
||||
def test_local_get_and_protocol_have_no_network_or_package_mutation(self):
|
||||
result = self.call('get')
|
||||
self.assertEqual(result['result'], 0)
|
||||
self.assertEqual(result['current_version'], '3.0.0-r1')
|
||||
self.assertFalse(result['can_upgrade'])
|
||||
self.assertEqual(result['upgrade']['phase'], 'idle')
|
||||
self.assertFalse(self.requests.exists())
|
||||
protocol = subprocess.check_output(['sh', str(self.script), 'list'], text=True)
|
||||
self.assertEqual(json.loads(protocol), {'get': {}, 'check': {}, 'status': {}, 'start': {'tag': 'String', 'package': 'String'}})
|
||||
self.env.update(APK_VERSION='', OPKG_VERSION='3.0.0-2')
|
||||
self.assertEqual(self.call('get')['package_manager'], 'opkg')
|
||||
self.assertEqual(self.call('get')['current_version'], '3.0.0-2')
|
||||
self.env['OPKG_VERSION'] = ''
|
||||
self.assertEqual(self.call('get')['current_version'], '')
|
||||
|
||||
def test_check_uses_official_url_and_highest_matching_revision(self):
|
||||
result = self.call('check', url='http://untrusted.invalid/', version='99.0.0')
|
||||
self.assertEqual(result['result'], 0)
|
||||
self.assertEqual(result['apk'], 'luci-theme-argon-3.0.0-r2.apk')
|
||||
self.assertEqual(result['ipk'], 'luci-theme-argon_3.0.0-2_all.ipk')
|
||||
self.assertEqual(result['notes'], self.release['body'])
|
||||
self.assertEqual(result['current_version'], '3.0.0-r1')
|
||||
requests = self.requests.read_text()
|
||||
self.assertIn(API, requests)
|
||||
self.assertIn('Cache-Control: no-cache', requests)
|
||||
self.assertNotIn('untrusted.invalid', requests)
|
||||
self.assertEqual(self.cache.stat().st_mode & 0o777, 0o600)
|
||||
|
||||
def test_success_cache_avoids_network_but_reloads_the_installed_version(self):
|
||||
self.call('check')
|
||||
before = self.requests.read_text()
|
||||
self.env['APK_VERSION'] = '3.0.0-r2'
|
||||
self.assertEqual(self.call('check')['current_version'], '3.0.0-r2')
|
||||
self.assertEqual(self.requests.read_text(), before)
|
||||
self.assertEqual(self.call('get')['tag'], 'v3.0.0')
|
||||
|
||||
def test_expired_or_future_cache_refreshes_and_failed_refresh_keeps_notes(self):
|
||||
first = self.call('check')
|
||||
for checked_at in [int(time.time()) - 400, int(time.time()) + 1000]:
|
||||
old = dict(first, checked_at=checked_at)
|
||||
self.cache.write_text(json.dumps(old))
|
||||
self.env['FETCH_FAIL'] = '1'
|
||||
self.assertEqual(self.call('check')['result'], 1)
|
||||
self.assertEqual(json.loads(self.cache.read_text()), old)
|
||||
self.assertEqual(self.call('get')['notes'], first['notes'])
|
||||
|
||||
def test_invalid_and_prerelease_responses_never_enter_cache(self):
|
||||
for value in ['not JSON', '{}', '[]', json.dumps(dict(self.release, draft=True)),
|
||||
json.dumps(dict(self.release, prerelease=True)),
|
||||
json.dumps(dict(self.release, tag_name='v3.1.0-beta.1'))]:
|
||||
with self.subTest(value=value[:60]):
|
||||
self.payload.write_text(value)
|
||||
self.assertNotEqual(self.call('check')['result'], 0)
|
||||
self.assertFalse(self.cache.exists())
|
||||
|
||||
def test_mismatched_and_unsafe_asset_names_are_ignored(self):
|
||||
self.release['assets'] = [{'name': name} for name in [
|
||||
'luci-theme-argon-4.0.0-r2.apk', 'luci-theme-argon_4.0.0_all.ipk',
|
||||
'luci-theme-argon-3.0.0-r2.apk?evil', 'luci-theme-argon_3.0.0-../../tmp_all.ipk']]
|
||||
self.payload.write_text(json.dumps(self.release))
|
||||
result = self.call('check')
|
||||
self.assertEqual(result['result'], 0)
|
||||
self.assertEqual(result['apk'], '')
|
||||
self.assertEqual(result['ipk'], '')
|
||||
|
||||
def test_linked_cache_is_not_read_or_overwritten_and_failed_download_is_retryable(self):
|
||||
outside = self.directory / 'outside'
|
||||
outside.write_text('keep me')
|
||||
self.cache.symlink_to(outside)
|
||||
self.assertNotIn('tag', self.call('get'))
|
||||
self.env['FETCH_FAIL'] = '1'
|
||||
self.assertEqual(self.call('check')['result'], 1)
|
||||
self.env['FETCH_FAIL'] = '0'
|
||||
self.assertEqual(self.call('check')['result'], 0)
|
||||
self.assertEqual(outside.read_text(), 'keep me')
|
||||
|
||||
def test_acl_separates_read_only_status_and_write_install(self):
|
||||
acl = json.loads((ROOT / 'root/usr/share/rpcd/acl.d/luci-app-argon-config.json').read_text())['luci-app-argon-config']
|
||||
self.assertEqual(set(acl['read']['ubus']['luci.argon_update']), {'get', 'check', 'status'})
|
||||
self.assertEqual(acl['write']['ubus']['luci.argon_update'], ['start'])
|
||||
|
||||
def start(self, **patch):
|
||||
return self.call('start', **dict({'tag': 'v3.0.0', 'package':
|
||||
'luci-theme-argon-3.0.0-r2.apk' if self.env['APK_VERSION'] else 'luci-theme-argon_3.0.0-2_all.ipk'}, **patch))
|
||||
|
||||
def finished(self):
|
||||
for _ in range(100):
|
||||
result = self.call('status')
|
||||
if not result['upgrade']['active']:
|
||||
return result
|
||||
time.sleep(.05)
|
||||
self.fail('worker did not finish')
|
||||
|
||||
def test_background_install_for_both_managers_and_status_survives_reloads(self):
|
||||
for manager in ['apk', 'opkg']:
|
||||
with self.subTest(manager=manager):
|
||||
installed = self.directory / 'installed'
|
||||
installed.unlink(missing_ok=True)
|
||||
self.env.update(APK_VERSION='3.0.0-r1' if manager == 'apk' else '',
|
||||
OPKG_VERSION='3.0.0-1' if manager == 'opkg' else '')
|
||||
checked = self.call('check')
|
||||
self.assertTrue(checked['can_upgrade'])
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
done = self.finished()
|
||||
self.assertEqual(done['upgrade']['phase'], 'complete', done)
|
||||
self.assertEqual(done['current_version'], '3.0.0-r2' if manager == 'apk' else '3.0.0-2')
|
||||
self.assertFalse(self.call('get')['can_upgrade'])
|
||||
self.assertEqual(self.call('get')['upgrade']['phase'], 'complete')
|
||||
command = (self.directory / 'mutations').read_text()
|
||||
self.assertNotIn('force-', command)
|
||||
self.assertIn('Theme installed', done['upgrade']['log'])
|
||||
self.assertEqual((self.directory / 'state/status.json').stat().st_mode & 0o777, 0o600)
|
||||
self.assertEqual(list((self.directory / 'state').glob('job.*')), [])
|
||||
|
||||
def test_start_rejects_changed_or_expired_metadata_unknown_versions_and_downgrades(self):
|
||||
self.assertEqual(self.start()['result'], 3)
|
||||
initial = self.call('check')
|
||||
for patch in [{'tag': 'v4.0.0'}, {'package': '../../unsafe.apk'}, {'package': 'luci-theme-argon-3.0.0-r1.apk'}]:
|
||||
self.assertEqual(self.start(**patch)['result'], 3)
|
||||
for value in ['unknown', '3.0.0-r2', '3.0.0-r20261015']:
|
||||
self.env['APK_VERSION'] = value
|
||||
self.assertEqual(self.start()['result'], 5)
|
||||
self.env['APK_VERSION'] = '3.0.0-r1'
|
||||
self.cache.write_text(json.dumps(dict(initial, checked_at=int(time.time()) - 301)))
|
||||
self.assertEqual(self.start()['result'], 3)
|
||||
self.assertFalse((self.directory / 'mutations').exists())
|
||||
|
||||
def test_unverified_assets_remain_manual_downloads(self):
|
||||
for patch in [{'digest': None}, {'digest': 'bad'}, {'size': 0}, {'size': 9000000}]:
|
||||
self.cache.unlink(missing_ok=True)
|
||||
release = dict(self.release, assets=[dict(self.release['assets'][2], **patch)])
|
||||
self.payload.write_text(json.dumps(release))
|
||||
checked = self.call('check')
|
||||
self.assertEqual(checked['apk'], 'luci-theme-argon-3.0.0-r2.apk')
|
||||
self.assertFalse(checked['can_upgrade'])
|
||||
self.assertEqual(self.start()['result'], 3)
|
||||
self.assertFalse((self.directory / 'mutations').exists())
|
||||
|
||||
def test_download_checksum_storage_and_package_manager_failures_are_retryable(self):
|
||||
self.call('check')
|
||||
for patch, error in [({'DOWNLOAD_FAIL': '1'}, 'network'), ({'FREE_KB': '10'}, 'space'),
|
||||
({'INSTALL_FAIL': '1'}, 'install'), ({'WRONG_VERSION': '1'}, 'install')]:
|
||||
with self.subTest(error=error):
|
||||
old = self.env.copy()
|
||||
self.env.update(patch)
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
result = self.finished()
|
||||
self.assertEqual(result['upgrade']['phase'], 'failed')
|
||||
self.assertEqual(result['upgrade']['error'], error, result)
|
||||
self.env = old
|
||||
(self.directory / 'package').write_bytes(b'wrong-package')
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
self.assertEqual(self.finished()['upgrade']['error'], 'checksum')
|
||||
(self.directory / 'package').write_bytes(b'argon-package')
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
self.assertEqual(self.finished()['upgrade']['phase'], 'complete')
|
||||
|
||||
def test_one_worker_at_a_time_and_private_metadata_snapshot(self):
|
||||
self.call('check')
|
||||
self.env['DOWNLOAD_DELAY'] = '4'
|
||||
start = time.monotonic()
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
self.assertLess(time.monotonic() - start, 3)
|
||||
self.assertEqual(self.start()['result'], 4)
|
||||
self.assertTrue(self.call('get')['upgrade']['active'])
|
||||
cached = json.loads(self.cache.read_text())
|
||||
cached['apk_sha256'] = '0' * 64
|
||||
self.cache.write_text(json.dumps(cached))
|
||||
self.assertEqual(self.finished()['upgrade']['phase'], 'complete')
|
||||
mutations = (self.directory / 'mutations').read_text()
|
||||
self.assertEqual(mutations.count('add'), 1)
|
||||
|
||||
def test_version_is_rechecked_after_download_before_mutation(self):
|
||||
self.call('check')
|
||||
self.env['DOWNLOAD_DELAY'] = '2'
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
(self.directory / 'installed').write_text('3.0.0-r2')
|
||||
self.assertEqual(self.finished()['upgrade']['error'], 'version')
|
||||
self.assertFalse((self.directory / 'mutations').exists())
|
||||
|
||||
def test_internal_worker_refuses_to_run_or_clean_up_outside_its_private_job(self):
|
||||
result = subprocess.run(['sh', str(self.script), 'run', 'apk'], env=self.env,
|
||||
capture_output=True, text=True)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertTrue(self.script.exists())
|
||||
self.assertTrue(self.payload.exists())
|
||||
self.assertFalse((self.directory / 'mutations').exists())
|
||||
|
||||
def test_interrupted_job_is_reported_without_a_stale_lock(self):
|
||||
state = self.directory / 'state'
|
||||
state.mkdir()
|
||||
(state / 'status.json').write_text(json.dumps({'phase': 'installing', 'version': '3.0.0-r2', 'error': ''}))
|
||||
self.assertEqual(self.call('status')['upgrade']['error'], 'interrupted')
|
||||
self.call('check')
|
||||
self.assertEqual(self.start()['result'], 0)
|
||||
self.assertEqual(self.finished()['upgrade']['phase'], 'complete')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,333 @@
|
||||
'use strict';
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
const source = fs.readFileSync(path.join(__dirname, '../htdocs/luci-static/resources/argon/updates.js'), 'utf8');
|
||||
String.prototype.format = function(value) { return this.replace('%s', value); };
|
||||
|
||||
function fixture(options = {}) {
|
||||
const state = { nodes: [], calls: [], args: [], watchers: new Set(), ...options };
|
||||
const E = (tag, attrs = {}, children = []) => {
|
||||
const node = { tag, attrs, children, isConnected: true, ...attrs, setAttribute(key, value) { this.attrs[key] = value; } };
|
||||
state.nodes.push(node);
|
||||
return node;
|
||||
};
|
||||
const rpc = { declare: spec => async (...args) => {
|
||||
assert.equal(spec.object, 'luci.argon_update');
|
||||
assert.equal(spec.raise, true);
|
||||
state.calls.push(spec.method);
|
||||
state.args.push(args);
|
||||
if (state[spec.method + 'Error']) throw new Error('network unavailable');
|
||||
if (spec.method === 'check') { await state.pending; return state.check; }
|
||||
if (spec.method === 'start') { await state.startPending; return state.start; }
|
||||
if (spec.method === 'status') return state.progress;
|
||||
return state.initial || { result: 0, current_version: '3.0.0-r1', package_manager: 'apk' };
|
||||
} };
|
||||
const ui = { showModal(title, children) { state.modal = { title, children }; }, hideModal() { state.modal = null; } };
|
||||
const poll = { add(fn) { state.watchers.add(fn); }, remove(fn) { state.watchers.delete(fn); } };
|
||||
state.api = new Function('baseclass', 'rpc', 'ui', 'poll', 'window', 'E', '_', source)(
|
||||
{ extend: v => v }, rpc, ui, poll, { location: { reload() { state.reloaded = true; } } }, E, v => v);
|
||||
state.render = async () => state.api.render(await state.api.load(), { readonly: !!state.readonly });
|
||||
state.find = (tag, value) => state.nodes.find(n => n.tag === tag && (n.textContent || n.children) === value);
|
||||
state.installButton = () => state.nodes.find(n => n.tag === 'button' && n.children === 'Update now');
|
||||
state.confirm = () => state.nodes.filter(n => n.tag === 'button' && n.children === 'Update now').at(-1).click();
|
||||
state.tick = () => Promise.all(Array.from(state.watchers, fn => fn()));
|
||||
state.button = () => state.nodes.find(n => n.tag === 'button');
|
||||
state.status = () => state.nodes.find(n => n.role === 'status').children[1].textContent;
|
||||
return state;
|
||||
}
|
||||
function checked(current, latest = '3.0.0-r2', manager = 'apk') {
|
||||
return { result: 0, can_upgrade: true, upgrade: { phase: 'idle', active: false }, current_version: current, package_manager: manager, tag: 'v' + latest.match(/^[0-9]+(?:\.[0-9]+)*/)[0],
|
||||
apk: manager === 'apk' ? 'luci-theme-argon-' + latest + '.apk' : '',
|
||||
ipk: manager === 'opkg' ? 'luci-theme-argon_' + latest + '_all.ipk' : '',
|
||||
notes: '## Changes\n\n- Fixed layout.', checked_at: 1792468800 };
|
||||
}
|
||||
|
||||
test('loading the settings reads local state without a remote check; checks are explicit', async () => {
|
||||
const f = fixture({ check: checked('3.0.0-r1') });
|
||||
await f.render();
|
||||
assert.deepEqual(f.calls, ['get']);
|
||||
assert.equal(f.status(), 'Not checked yet.');
|
||||
assert.equal(f.find('a', 'Download package').hidden, true);
|
||||
await f.button().click();
|
||||
assert.deepEqual(f.calls, ['get', 'check']);
|
||||
assert.equal(f.status(), 'Update available.');
|
||||
assert.match(f.find('a', 'Download package').href, /v3\.0\.0\/luci-theme-argon-3\.0\.0-r2\.apk$/);
|
||||
assert.equal(f.nodes.find(n => n.tag === 'details').open, true);
|
||||
});
|
||||
|
||||
test('package revisions, numeric versions, prereleases and locally newer builds compare correctly', async () => {
|
||||
for (const [current, latest, manager, expected] of [
|
||||
['3.0.0-r1', '3.0.0-r2', 'apk', 'Update available.'],
|
||||
['3.0.0', '3.0.0-2', 'opkg', 'Update available.'],
|
||||
['3.0.0-2', '3.0.0-2', 'opkg', 'Your theme is up to date.'],
|
||||
['3.0.0-r2', '3.0.0-r2', 'apk', 'Your theme is up to date.'],
|
||||
['3.0.0-r20261015', '3.0.0-r2', 'apk', 'The installed version is newer than the latest stable release.'],
|
||||
['3.0.0-r20261015', '3.0.1-r1', 'apk', 'Update available.'],
|
||||
['3.9.0-r1', '3.10.0-r1', 'apk', 'Update available.'],
|
||||
['3.0.0_rc1-r2', '3.0.0-r1', 'apk', 'Update available.'],
|
||||
['3.0.0~beta1-2', '3.0.0', 'opkg', 'Update available.'],
|
||||
['unknown', '3.0.0-r2', 'apk', 'Unable to compare this version. View the release for details.']
|
||||
]) {
|
||||
const f = fixture({ initial: checked(current, latest, manager) });
|
||||
await f.render();
|
||||
assert.equal(f.status(), expected, `${current} / ${latest}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('unmatched packages and unknown managers cannot produce an up-to-date claim or download link', async () => {
|
||||
for (const patch of [{ apk: 'luci-theme-argon-4.0.0-r2.apk' }, { apk: '../../unsafe.apk' }, { package_manager: 'unknown' }, { apk: '' }]) {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r2'), ...patch } });
|
||||
await f.render();
|
||||
assert.equal(f.find('a', 'Download package').hidden, true);
|
||||
assert.equal(f.status(), 'Unable to compare this version. View the release for details.');
|
||||
}
|
||||
});
|
||||
|
||||
test('repeated clicks share a check and restore the button after transport or backend failure', async () => {
|
||||
for (const patch of [{ checkError: true }, { check: { result: 1 } }, { check: { result: 0, tag: 'not-a-version' } }]) {
|
||||
let finish;
|
||||
const f = fixture({ ...patch, pending: new Promise(resolve => { finish = resolve; }) });
|
||||
await f.render();
|
||||
const first = f.button().click();
|
||||
assert.equal(f.button().disabled, true);
|
||||
await f.button().click();
|
||||
assert.deepEqual(f.calls, ['get', 'check']);
|
||||
finish(); await first;
|
||||
assert.equal(f.button().disabled, false);
|
||||
assert.match(f.status(), /^Unable to check for updates/);
|
||||
}
|
||||
});
|
||||
|
||||
test('failed checks preserve cached notes, versions and release links', async () => {
|
||||
const f = fixture({ initial: checked('3.0.0-r1'), checkError: true });
|
||||
await f.render();
|
||||
const link = f.find('a', 'View release').href;
|
||||
const notes = f.nodes.find(n => n.tag === 'pre').textContent;
|
||||
await f.button().click();
|
||||
assert.equal(f.find('a', 'View release').href, link);
|
||||
assert.equal(f.nodes.find(n => n.tag === 'pre').textContent, notes);
|
||||
assert.match(f.status(), /^Unable to check for updates/);
|
||||
});
|
||||
|
||||
test('release notes remain text, are bounded, and have an explicit empty state', async () => {
|
||||
for (const text of ['<img src=x onerror=alert(1)>\n<script>alert(1)</script>', '', '文'.repeat(40000)]) {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r2'), notes: text } });
|
||||
await f.render();
|
||||
const notes = f.nodes.find(n => n.tag === 'pre');
|
||||
assert.equal(notes.innerHTML, undefined);
|
||||
assert.equal(notes.textContent, text ? text.slice(0,32768) + (text.length > 32768 ? '\n…' : '') : 'No release notes were published.');
|
||||
}
|
||||
});
|
||||
|
||||
test('a failed local state load can recover through a manual check', async () => {
|
||||
const f = fixture({ getError: true, check: checked('3.0.0-r1') });
|
||||
await f.render();
|
||||
assert.match(f.status(), /^Unable to check for updates/);
|
||||
await f.button().click();
|
||||
assert.equal(f.status(), 'Update available.');
|
||||
});
|
||||
|
||||
|
||||
test('installation is offered only for an upgrade with backend verification and write access', async () => {
|
||||
for (const [patch, readonly, visible] of [
|
||||
[{}, false, true], [{ can_upgrade: false }, false, false], [{ current_version: '3.0.0-r2' }, false, false],
|
||||
[{ current_version: '3.0.0-r20261015' }, false, false], [{ apk: '' }, false, false], [{}, true, false]
|
||||
]) {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r1'), ...patch }, readonly });
|
||||
await f.render();
|
||||
assert.equal(f.installButton().hidden, !visible);
|
||||
if (!visible) { f.installButton().click(); assert.equal(f.modal, undefined); }
|
||||
}
|
||||
});
|
||||
|
||||
test('confirmation names the version and cancellation never starts installation', async () => {
|
||||
const f = fixture({ initial: checked('3.0.0-r1') });
|
||||
await f.render();
|
||||
f.installButton().click();
|
||||
assert.equal(f.modal.title, 'Update Argon to 3.0.0-r2?');
|
||||
assert.equal(f.button().disabled, true);
|
||||
await f.button().click();
|
||||
f.find('button', 'Cancel').click();
|
||||
assert.equal(f.modal, null);
|
||||
assert.equal(f.installButton().disabled, false);
|
||||
assert.deepEqual(f.calls, ['get']);
|
||||
});
|
||||
|
||||
test('confirmed upgrade runs once, polls phases, records plain logs and offers a reload', async () => {
|
||||
const f = fixture({ initial: checked('3.0.0-r1'), start: { result: 0, upgrade: { phase: 'starting', active: true } } });
|
||||
await f.render(); f.installButton().click(); await f.confirm();
|
||||
assert.deepEqual(f.calls, ['get', 'start']);
|
||||
assert.deepEqual(f.args.at(-1), ['v3.0.0', 'luci-theme-argon-3.0.0-r2.apk']);
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.equal(f.button().disabled, true);
|
||||
f.installButton().click();
|
||||
await f.button().click();
|
||||
assert.deepEqual(f.calls, ['get', 'start']);
|
||||
for (const [phase, text] of [['downloading', 'Downloading the update...'], ['verifying', 'Verifying the package...'], ['installing', 'Installing the update. Please wait...']]) {
|
||||
f.progress = { result: 0, current_version: '3.0.0-r1', upgrade: { phase, active: true } };
|
||||
await f.tick(); assert.equal(f.status(), text);
|
||||
}
|
||||
const upgrade = { phase: 'complete', active: false, log: '<script>bad()</script>Installed' };
|
||||
f.progress = { result: 0, current_version: '3.0.0-r2', upgrade };
|
||||
f.initial = { ...checked('3.0.0-r2'), can_upgrade: false, upgrade };
|
||||
await f.tick();
|
||||
assert.equal(f.watchers.size, 0);
|
||||
assert.equal(f.installButton().hidden, true);
|
||||
assert.match(f.status(), /^Update installed/);
|
||||
const log = f.nodes.filter(n => n.tag === 'pre').at(-1);
|
||||
assert.equal(log.textContent, upgrade.log);
|
||||
assert.equal(log.innerHTML, undefined);
|
||||
const reload = f.find('button', 'Reload page');
|
||||
assert.equal(reload.hidden, false);
|
||||
reload.click(); assert.equal(f.reloaded, true);
|
||||
});
|
||||
|
||||
test('page reload resumes monitoring; connection failures keep installation disabled until status recovers', async () => {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r1'), upgrade: { phase: 'installing', active: true } }, statusError: true });
|
||||
await f.render(); assert.equal(f.watchers.size, 1);
|
||||
await f.tick(); assert.match(f.status(), /^Unable to read update progress/);
|
||||
assert.equal(f.installButton().disabled, true);
|
||||
f.statusError = false;
|
||||
const upgrade = { phase: 'failed', active: false, error: 'install', log: 'database locked' };
|
||||
f.initial = { ...checked('3.0.0-r1'), upgrade };
|
||||
f.progress = { result: 0, current_version: '3.0.0-r1', upgrade };
|
||||
await f.tick();
|
||||
assert.equal(f.watchers.size, 0);
|
||||
assert.equal(f.installButton().disabled, false);
|
||||
assert.match(f.status(), /^Installation failed/);
|
||||
});
|
||||
|
||||
test('a lost start response cannot trigger a duplicate installation and stale metadata requires another check', async () => {
|
||||
const f = fixture({ initial: checked('3.0.0-r1'), startError: true });
|
||||
await f.render(); f.installButton().click(); await f.confirm();
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.match(f.status(), /^Unable to read update progress/);
|
||||
f.installButton().click(); assert.equal(f.calls.filter(m => m === 'start').length, 1);
|
||||
for (const result of [3, 5]) {
|
||||
const stale = fixture({ initial: checked('3.0.0-r1'), start: { result } });
|
||||
await stale.render(); stale.installButton().click(); await stale.confirm();
|
||||
assert.equal(stale.watchers.size, 0);
|
||||
assert.equal(stale.installButton().hidden, true);
|
||||
assert.match(stale.status(), /Check for updates again/);
|
||||
}
|
||||
});
|
||||
|
||||
test('monitoring stops when its card is removed', async () => {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r1'), upgrade: { phase: 'installing', active: true } } });
|
||||
await f.render();
|
||||
f.progress = { result: 0, current_version: '3.0.0-r1', upgrade: { phase: 'installing', active: true } };
|
||||
await f.tick();
|
||||
f.nodes.find(n => n.attrs.class === 'argon-update-content').isConnected = false;
|
||||
await f.tick();
|
||||
assert.equal(f.watchers.size, 0);
|
||||
assert.deepEqual(f.calls, ['get', 'status']);
|
||||
});
|
||||
|
||||
|
||||
test('an early idle poll cannot finish monitoring before the start response arrives', async () => {
|
||||
let accept;
|
||||
const f = fixture({ initial: checked('3.0.0-r1'), startPending: new Promise(resolve => { accept = resolve; }),
|
||||
start: { result: 0, upgrade: { phase: 'starting', active: true } },
|
||||
progress: { result: 0, current_version: '3.0.0-r1', upgrade: { phase: 'idle', active: false } } });
|
||||
await f.render(); f.installButton().click(); const starting = f.confirm();
|
||||
await f.tick();
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.equal(f.installButton().disabled, true);
|
||||
accept(); await starting;
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.equal(f.calls.filter(m => m === 'start').length, 1);
|
||||
assert.equal(f.status(), 'Preparing the update...');
|
||||
});
|
||||
|
||||
test('a resumed job waits for its card to mount before polling', async () => {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r1'), upgrade: { phase: 'installing', active: true } },
|
||||
progress: { result: 0, current_version: '3.0.0-r1', upgrade: { phase: 'installing', active: true } } });
|
||||
await f.render();
|
||||
const content = f.nodes.find(n => n.attrs.class === 'argon-update-content');
|
||||
content.isConnected = false; await f.tick();
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.deepEqual(f.calls, ['get']);
|
||||
content.isConnected = true; await f.tick();
|
||||
assert.deepEqual(f.calls, ['get', 'status']);
|
||||
});
|
||||
|
||||
test('monitoring follows a new job started while the previous terminal status was being read', async () => {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r1'), upgrade: { phase: 'installing', active: true } },
|
||||
progress: { result: 0, current_version: '3.0.0-r1', upgrade: { phase: 'failed', active: false, error: 'install' } } });
|
||||
await f.render();
|
||||
f.initial = { ...checked('3.0.0-r1'), upgrade: { phase: 'downloading', active: true } };
|
||||
await f.tick();
|
||||
assert.equal(f.watchers.size, 1);
|
||||
assert.equal(f.installButton().disabled, true);
|
||||
assert.equal(f.status(), 'Downloading the update...');
|
||||
});
|
||||
|
||||
|
||||
test('historical successful installs render as up to date after reloading, without pending update actions', async () => {
|
||||
for (const manager of ['apk', 'opkg']) {
|
||||
const current = manager === 'apk' ? '3.0.0-r2' : '3.0.0-2';
|
||||
const initial = { ...checked(current, current, manager), can_upgrade: false,
|
||||
upgrade: { phase: 'complete', active: false, version: current, log: 'Installed' } };
|
||||
const f = fixture({ initial, check: initial });
|
||||
await f.render();
|
||||
assert.equal(f.status(), 'Your theme is up to date.');
|
||||
assert.equal(f.find('button', 'Reload page').hidden, true);
|
||||
assert.equal(f.installButton().hidden, true);
|
||||
assert.equal(f.find('a', 'Download package').hidden, true);
|
||||
assert.equal(f.nodes.find(n => n.role === 'status').attrs['data-state'], 'current');
|
||||
assert.equal(f.nodes.find(n => n.attrs.class === 'argon-update-status-icon').hidden, false);
|
||||
assert.ok(f.nodes.filter(n => n.tag === 'details').every(n => !n.open));
|
||||
await f.button().click();
|
||||
assert.equal(f.status(), 'Your theme is up to date.');
|
||||
assert.ok(f.nodes.filter(n => n.tag === 'details').every(n => !n.open));
|
||||
assert.equal(f.find('button', 'Reload page').hidden, true);
|
||||
}
|
||||
});
|
||||
|
||||
test('a previous completed job cannot conceal a newly available release', async () => {
|
||||
const f = fixture({ initial: { ...checked('3.0.0-r2', '3.0.0-r3'),
|
||||
upgrade: { phase: 'complete', active: false, version: '3.0.0-r2' } } });
|
||||
await f.render();
|
||||
assert.equal(f.status(), 'Update available.');
|
||||
assert.equal(f.installButton().hidden, false);
|
||||
assert.equal(f.find('button', 'Reload page').hidden, true);
|
||||
assert.equal(f.find('a', 'Download package').hidden, false);
|
||||
});
|
||||
|
||||
test('completion collapses notes once and requires a reload for a job observed in this document', async () => {
|
||||
const current = '3.0.0-r2';
|
||||
const f = fixture({ initial: { ...checked(current),
|
||||
upgrade: { phase: 'installing', active: true, version: current } } });
|
||||
await f.render();
|
||||
const details = f.nodes.filter(n => n.tag === 'details');
|
||||
details.forEach(n => { n.open = true; });
|
||||
const upgrade = { phase: 'complete', active: false, version: current, log: 'Installed' };
|
||||
f.initial = { ...checked(current), can_upgrade: false, upgrade };
|
||||
f.progress = { result: 0, current_version: current, upgrade };
|
||||
await f.tick();
|
||||
assert.match(f.status(), /^Update installed/);
|
||||
assert.equal(f.find('button', 'Reload page').hidden, false);
|
||||
assert.ok(details.every(n => !n.open));
|
||||
assert.equal(f.find('a', 'Download package').hidden, true);
|
||||
});
|
||||
|
||||
test('recovering a failed local read does not treat a historical installation as a new one', async () => {
|
||||
const f = fixture({ getError: true, check: { ...checked('3.0.0-r2'), can_upgrade: false,
|
||||
upgrade: { phase: 'complete', active: false, version: '3.0.0-r2' } } });
|
||||
await f.render(); await f.button().click();
|
||||
assert.equal(f.status(), 'Your theme is up to date.');
|
||||
assert.equal(f.find('button', 'Reload page').hidden, true);
|
||||
});
|
||||
|
||||
test('failed refreshes remove the success icon while preserving the last checked versions', async () => {
|
||||
const f = fixture({ initial: checked('3.0.0-r2'), checkError: true });
|
||||
await f.render();
|
||||
const icon = f.nodes.find(n => n.attrs.class === 'argon-update-status-icon');
|
||||
assert.equal(icon.hidden, false);
|
||||
await f.button().click();
|
||||
assert.match(f.status(), /^Unable to check for updates/);
|
||||
assert.equal(icon.hidden, true);
|
||||
assert.equal(f.nodes.find(n => n.role === 'status').attrs['data-state'], 'error');
|
||||
});
|
||||
@@ -20,12 +20,14 @@
|
||||
import { getuid, getspnam } from 'luci.core';
|
||||
|
||||
const hostname = striptags(ubus.call('system', 'board')?.hostname ?? '?');
|
||||
// First-child routes keep the entry URL while resolving to a deeper page.
|
||||
const page_path = length(ctx.path) > length(ctx.request_path) ? ctx.path : ctx.request_path;
|
||||
include('themes/' + theme + '/head', { hostname: hostname, is_login: false });
|
||||
%}
|
||||
|
||||
<body
|
||||
class="lang_{{ dispatcher.lang }} {{ node?.title ? ` - ${striptags(node.title)}` : '' }} {% if (ctx.authsession): %}logged-in{% endif %}"
|
||||
data-page="{{ entityencode(join('-', ctx.request_path), true) }}">
|
||||
data-page="{{ entityencode(join('-', page_path), true) }}">
|
||||
|
||||
<div class="main">
|
||||
<div class="main-left" id="mainmenu" style="display:none">
|
||||
|
||||
Reference in new issue
Block a user