Skip to content

Commit 472853e

Browse files
committed
localize subscription settings tab (replace hardcoded strings with t())
1 parent c7e4087 commit 472853e

3 files changed

Lines changed: 58 additions & 20 deletions

File tree

src/locales/en.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,22 @@
711711
"subUpdateIntervalHint": "How often clients auto-refresh the subscription. Sent as the Profile-Update-Interval response header. Range: 1–168 hours.",
712712
"subButtons": "Buttons on subscription page",
713713
"subButtonsHint": "Use {url} in the URL field to insert the subscription link (e.g. hiddify://import/{url}). For Shadowrocket use sub://{url_b64}. For query params use {url_encoded}. Icons: tabler.io/icons (e.g. ti-download).",
714-
"subAddButton": "Add button"
714+
"subAddButton": "Add button",
715+
"subLogoDefault": "Default",
716+
"subHiddifyProfileHint": "The links below appear in Hiddify / Clash as profile card buttons.",
717+
"subPageTitlePlaceholder": "Connection",
718+
"subTemplate": "Template",
719+
"subTplClients": "Clients",
720+
"subTplLinks": "Links",
721+
"subTplSupport": "Support",
722+
"subTplWebsite": "Website",
723+
"subIconSearch": "Search…",
724+
"subBtnLabelPlaceholder": "Hiddify",
725+
"subBtnUrlPlaceholder": "hiddify://import/{url}",
726+
"subBtnLabelTitle": "Button label",
727+
"subBtnUrlTitle": "URL — placeholders: {url}, {url_b64}, {url_encoded}",
728+
"subPickIcon": "Choose icon",
729+
"subDeleteBtn": "Remove"
715730
},
716731
"setup": {
717732
"title": "Initial Setup",

src/locales/ru.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,22 @@
711711
"subUpdateIntervalHint": "Как часто клиенты автоматически обновляют подписку. Передаётся в заголовке Profile-Update-Interval. Диапазон: 1–168 часов.",
712712
"subButtons": "Кнопки на странице подписки",
713713
"subButtonsHint": "Используйте {url} в поле URL для подстановки ссылки подписки (например: hiddify://import/{url}). Для Shadowrocket: sub://{url_b64}. Для query-параметров: {url_encoded}. Иконки: tabler.io/icons (например: ti-download).",
714-
"subAddButton": "Добавить кнопку"
714+
"subAddButton": "Добавить кнопку",
715+
"subLogoDefault": "по умолчанию",
716+
"subHiddifyProfileHint": "Ссылки ниже отображаются в клиентах Hiddify / Clash как кнопки в карточке профиля.",
717+
"subPageTitlePlaceholder": "Подключение",
718+
"subTemplate": "Шаблон",
719+
"subTplClients": "Клиенты",
720+
"subTplLinks": "Ссылки",
721+
"subTplSupport": "Поддержка",
722+
"subTplWebsite": "Сайт",
723+
"subIconSearch": "Поиск…",
724+
"subBtnLabelPlaceholder": "Hiddify",
725+
"subBtnUrlPlaceholder": "hiddify://import/{url}",
726+
"subBtnLabelTitle": "Название кнопки",
727+
"subBtnUrlTitle": "URL — переменные: {url}, {url_b64}, {url_encoded}",
728+
"subPickIcon": "Выбрать иконку",
729+
"subDeleteBtn": "Удалить"
715730
},
716731
"setup": {
717732
"title": "Первоначальная настройка",

views/partials/settings/subscription.ejs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</div>
3030
<div id="logoDefaultPreview" style="color: var(--text-muted); font-size: 13px; <%= settings?.subscription?.logoUrl ? 'display:none;' : '' %>">
3131
<i class="ti ti-rocket" style="font-size: 32px;"></i>
32-
<div style="font-size: 11px; margin-top: 4px;">по умолчанию</div>
32+
<div style="font-size: 11px; margin-top: 4px;"><%= t('settings.subLogoDefault') %></div>
3333
</div>
3434
</div>
3535
</div>
@@ -38,15 +38,15 @@
3838
<label><%= t('settings.subPageTitle') || 'Заголовок страницы' %></label>
3939
<input type="text" name="subscription.pageTitle"
4040
value="<%= settings?.subscription?.pageTitle || '' %>"
41-
placeholder="Подключение">
41+
placeholder="<%= t('settings.subPageTitlePlaceholder') %>">
4242
<small class="hint"><%= t('settings.subPageTitleHint') || 'Текст над логотипом. По умолчанию: «Подключение».' %></small>
4343
</div>
4444

4545
<hr style="margin: 1.25rem 0; border-color: var(--border);">
4646

4747
<p style="font-size: 13px; color: var(--text-muted); margin-bottom: 1rem;">
4848
<i class="ti ti-info-circle"></i>
49-
Ссылки ниже отображаются в клиентах Hiddify / Clash как кнопки в карточке профиля.
49+
<%= t('settings.subHiddifyProfileHint') %>
5050
</p>
5151

5252
<div class="settings-grid">
@@ -98,8 +98,7 @@
9898
</div>
9999
<p style="font-size: 12px; color: var(--text-muted); margin-bottom: 0.75rem; line-height: 1.5;">
100100
<i class="ti ti-info-circle"></i>
101-
Используйте <code>{url}</code> в URL для подстановки ссылки подписки (например: <code>hiddify://import/{url}</code>).
102-
Для Shadowrocket: <code>sub://{url_b64}</code>. Для query-параметров: <code>{url_encoded}</code>.
101+
<%= t('settings.subButtonsHint') %>
103102
</p>
104103
<input type="hidden" name="subscription.buttonsJson" id="subButtonsJson" value="">
105104
<div id="subButtonsList" style="display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px;"></div>
@@ -109,21 +108,21 @@
109108
</button>
110109
<div style="position: relative; display: inline-block;">
111110
<button type="button" class="btn btn-secondary" style="font-size: 13px;" onclick="this.nextElementSibling.classList.toggle('open')">
112-
<i class="ti ti-template"></i> Шаблон
111+
<i class="ti ti-template"></i> <%= t('settings.subTemplate') %>
113112
</button>
114113
<div class="tpl-dropdown">
115-
<div class="tpl-section">Клиенты</div>
114+
<div class="tpl-section"><%= t('settings.subTplClients') %></div>
116115
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Hiddify" data-url="hiddify://import/{url}" data-icon="ti-download"><i class="ti ti-download"></i> Hiddify</div>
117116
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Streisand" data-url="streisand://import/{url}" data-icon="ti-shield"><i class="ti ti-shield"></i> Streisand</div>
118117
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="V2RayNG" data-url="v2rayng://install-sub?url={url_encoded}" data-icon="ti-brand-android"><i class="ti ti-brand-android"></i> V2RayNG</div>
119118
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Shadowrocket" data-url="sub://{url_b64}" data-icon="ti-brand-apple"><i class="ti ti-brand-apple"></i> Shadowrocket</div>
120119
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Clash" data-url="clash://install-config?url={url_encoded}" data-icon="ti-bolt"><i class="ti ti-bolt"></i> Clash / Stash</div>
121120
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Sing-box" data-url="sing-box://import-remote-profile?url={url_encoded}" data-icon="ti-box-multiple"><i class="ti ti-box-multiple"></i> Sing-box</div>
122121
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="HAPP" data-url="{url}" data-icon="ti-rocket"><i class="ti ti-rocket"></i> HAPP</div>
123-
<div class="tpl-section">Ссылки</div>
124-
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Поддержка" data-url="https://t.me/" data-icon="ti-brand-telegram"><i class="ti ti-brand-telegram"></i> Telegram</div>
122+
<div class="tpl-section"><%= t('settings.subTplLinks') %></div>
123+
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="<%= t('settings.subTplSupport') %>" data-url="https://t.me/" data-icon="ti-brand-telegram"><i class="ti ti-brand-telegram"></i> Telegram</div>
125124
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Email" data-url="mailto:" data-icon="ti-mail"><i class="ti ti-mail"></i> Email</div>
126-
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="Сайт" data-url="https://" data-icon="ti-world"><i class="ti ti-world"></i> Сайт</div>
125+
<div class="tpl-item" onclick="subFromTemplate(this)" data-label="<%= t('settings.subTplWebsite') %>" data-url="https://" data-icon="ti-world"><i class="ti ti-world"></i> <%= t('settings.subTplWebsite') %></div>
127126
</div>
128127
</div>
129128
</div>
@@ -159,6 +158,15 @@
159158

160159
<script>
161160
(function() {
161+
var subI18n = {
162+
search: <%- JSON.stringify(t('settings.subIconSearch')) %>,
163+
btnLabelPh: <%- JSON.stringify(t('settings.subBtnLabelPlaceholder')) %>,
164+
btnUrlPh: <%- JSON.stringify(t('settings.subBtnUrlPlaceholder')) %>,
165+
btnLabelTitle: <%- JSON.stringify(t('settings.subBtnLabelTitle')) %>,
166+
btnUrlTitle: <%- JSON.stringify(t('settings.subBtnUrlTitle')) %>,
167+
pickIcon: <%- JSON.stringify(t('settings.subPickIcon')) %>,
168+
deleteBtn: <%- JSON.stringify(t('settings.subDeleteBtn')) %>,
169+
};
162170
var ICONS = [
163171
'ti-download','ti-external-link','ti-link','ti-share','ti-send','ti-copy','ti-cloud-download',
164172
'ti-brand-telegram','ti-brand-whatsapp','ti-brand-discord','ti-brand-twitter','ti-brand-github',
@@ -187,7 +195,7 @@
187195
188196
var picker = document.createElement('div');
189197
picker.className = 'icon-picker';
190-
picker.innerHTML = '<input type="text" class="icon-picker-search" placeholder="Поиск...">'
198+
picker.innerHTML = '<input type="text" class="icon-picker-search" placeholder=' + JSON.stringify(subI18n.search) + '>'
191199
+ '<div class="icon-picker-grid"></div>';
192200
document.body.appendChild(picker);
193201
@@ -231,7 +239,7 @@
231239
if (!pickerTarget) return;
232240
pickerTarget.row._btnIcon = ic;
233241
pickerTarget.btn.innerHTML = '<i class="ti ' + ic + '"></i>';
234-
pickerTarget.btn.title = ic;
242+
pickerTarget.btn.title = subI18n.pickIcon;
235243
picker.classList.remove('open');
236244
pickerTarget = null;
237245
syncJson();
@@ -281,33 +289,33 @@
281289
282290
var labelInp = document.createElement('input');
283291
labelInp.type = 'text';
284-
labelInp.placeholder = 'Hiddify';
292+
labelInp.placeholder = subI18n.btnLabelPh;
285293
labelInp.value = data.label || '';
286294
labelInp.style.cssText = 'min-width:0;';
287-
labelInp.title = 'Название кнопки';
295+
labelInp.title = subI18n.btnLabelTitle;
288296
labelInp.oninput = syncJson;
289297
row._labelInp = labelInp;
290298
291299
var urlInp = document.createElement('input');
292300
urlInp.type = 'text';
293-
urlInp.placeholder = 'hiddify://import/{url}';
301+
urlInp.placeholder = subI18n.btnUrlPh;
294302
urlInp.value = data.url || '';
295303
urlInp.style.cssText = 'min-width:0; font-size:12px;';
296-
urlInp.title = 'URL — переменные: {url}, {url_b64}, {url_encoded}';
304+
urlInp.title = subI18n.btnUrlTitle;
297305
urlInp.oninput = syncJson;
298306
row._urlInp = urlInp;
299307
300308
var iconBtn = document.createElement('div');
301309
iconBtn.className = 'icon-pick-btn';
302-
iconBtn.title = iconVal || 'Выбрать иконку';
310+
iconBtn.title = subI18n.pickIcon;
303311
iconBtn.innerHTML = iconDisplay;
304312
iconBtn.onclick = function() { openPicker(iconBtn, row); };
305313
306314
var delBtn = document.createElement('button');
307315
delBtn.type = 'button';
308316
delBtn.className = 'btn btn-danger';
309317
delBtn.style.cssText = 'padding:0.4rem 0.6rem; flex-shrink:0;';
310-
delBtn.title = 'Удалить';
318+
delBtn.title = subI18n.deleteBtn;
311319
delBtn.innerHTML = '<i class="ti ti-trash" style="font-size:14px;"></i>';
312320
delBtn.onclick = function() { row.remove(); updateCount(); syncJson(); };
313321

0 commit comments

Comments
 (0)