refactor(ui): i18n: remove unnecessary wrappers
This commit is contained in:
@@ -3,11 +3,6 @@ import { i18n } from '../../core/i18n.js';
|
||||
|
||||
const API = '/api';
|
||||
|
||||
/* ── i18n helper ── */
|
||||
function t(key, params) {
|
||||
return i18n.t(key, params);
|
||||
}
|
||||
|
||||
function headers() {
|
||||
return { 'Content-Type': 'application/json', ...getCsrfHeaders() };
|
||||
}
|
||||
@@ -21,14 +16,14 @@ function formatBytes(bytes) {
|
||||
}
|
||||
|
||||
function timeAgo(dateStr) {
|
||||
if (!dateStr) return t('profile.never');
|
||||
if (!dateStr) return i18n.t('profile.never');
|
||||
const d = new Date(dateStr);
|
||||
const now = new Date();
|
||||
const secs = Math.floor((now - d) / 1000);
|
||||
if (secs < 60) return t('profile.just_now');
|
||||
if (secs < 3600) return t('profile.minutes_ago', { n: Math.floor(secs / 60) });
|
||||
if (secs < 86400) return t('profile.hours_ago', { n: Math.floor(secs / 3600) });
|
||||
if (secs < 2592000) return t('profile.days_ago', { n: Math.floor(secs / 86400) });
|
||||
if (secs < 60) return i18n.t('profile.just_now');
|
||||
if (secs < 3600) return i18n.t('profile.minutes_ago', { n: Math.floor(secs / 60) });
|
||||
if (secs < 86400) return i18n.t('profile.hours_ago', { n: Math.floor(secs / 3600) });
|
||||
if (secs < 2592000) return i18n.t('profile.days_ago', { n: Math.floor(secs / 86400) });
|
||||
return d.toLocaleDateString();
|
||||
}
|
||||
|
||||
@@ -52,15 +47,15 @@ async function init() {
|
||||
const badge = document.getElementById('p-role-badge');
|
||||
if (user.role === 'admin') {
|
||||
badge.className = 'role-badge role-badge-admin';
|
||||
badge.innerHTML = `<i class="fas fa-shield-alt"></i> ${t('profile.role_admin')}`;
|
||||
badge.innerHTML = `<i class="fas fa-shield-alt"></i> ${i18n.t('profile.role_admin')}`;
|
||||
} else {
|
||||
badge.className = 'role-badge role-badge-user';
|
||||
badge.innerHTML = `<i class="fas fa-user"></i> ${t('profile.role_user')}`;
|
||||
badge.innerHTML = `<i class="fas fa-user"></i> ${i18n.t('profile.role_user')}`;
|
||||
}
|
||||
|
||||
document.getElementById('p-detail-username').textContent = user.username;
|
||||
document.getElementById('p-detail-email').textContent = user.email || '—';
|
||||
document.getElementById('p-detail-role').textContent = user.role === 'admin' ? t('profile.role_admin') : t('profile.role_user');
|
||||
document.getElementById('p-detail-role').textContent = user.role === 'admin' ? i18n.t('profile.role_admin') : i18n.t('profile.role_user');
|
||||
document.getElementById('p-detail-login').textContent = timeAgo(user.last_login_at);
|
||||
|
||||
const used = user.storage_used_bytes || 0;
|
||||
@@ -74,7 +69,7 @@ async function init() {
|
||||
const bar = document.getElementById('p-storage-bar');
|
||||
bar.style.width = `${pct}%`;
|
||||
bar.className = `storage-fill ${pct > 90 ? 'red' : pct > 70 ? 'orange' : 'green'}`;
|
||||
document.getElementById('p-storage-text').textContent = `${formatBytes(used)} / ${quota > 0 ? formatBytes(quota) : t('profile.unlimited')}`;
|
||||
document.getElementById('p-storage-text').textContent = `${formatBytes(used)} / ${quota > 0 ? formatBytes(quota) : i18n.t('profile.unlimited')}`;
|
||||
|
||||
if (user.auth_provider && user.auth_provider !== 'local') {
|
||||
document.getElementById('password-section').classList.add('hidden');
|
||||
@@ -115,18 +110,18 @@ async function changePassword(e) {
|
||||
const statusEl = document.getElementById('pw-status');
|
||||
|
||||
if (newPw !== confirmPw) {
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(t('profile.passwords_no_match'))}</div>`;
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(i18n.t('profile.passwords_no_match'))}</div>`;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newPw.length < 8) {
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(t('profile.password_too_short'))}</div>`;
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(i18n.t('profile.password_too_short'))}</div>`;
|
||||
return false;
|
||||
}
|
||||
|
||||
const btn = document.getElementById('pw-submit');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(t('profile.updating'))}`;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(i18n.t('profile.updating'))}`;
|
||||
|
||||
try {
|
||||
const resp = await fetch(`${API}/auth/change-password`, {
|
||||
@@ -140,24 +135,24 @@ async function changePassword(e) {
|
||||
});
|
||||
|
||||
if (resp.ok) {
|
||||
statusEl.innerHTML = `<div class="alert alert-success"><i class="fas fa-check-circle"></i> ${escapeHtml(t('profile.password_updated'))}</div>`;
|
||||
statusEl.innerHTML = `<div class="alert alert-success"><i class="fas fa-check-circle"></i> ${escapeHtml(i18n.t('profile.password_updated'))}</div>`;
|
||||
document.getElementById('password-form').reset();
|
||||
} else {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
statusEl.innerHTML =
|
||||
'<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ' +
|
||||
escapeHtml(err.message || t('profile.password_change_failed')) +
|
||||
escapeHtml(err.message || i18n.t('profile.password_change_failed')) +
|
||||
'</div>';
|
||||
}
|
||||
} catch (err) {
|
||||
statusEl.innerHTML =
|
||||
'<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ' +
|
||||
escapeHtml(t('profile.error_network', { message: err.message })) +
|
||||
escapeHtml(i18n.t('profile.error_network', { message: err.message })) +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = `<i class="fas fa-save"></i> ${escapeHtml(t('profile.update_password'))}`;
|
||||
btn.innerHTML = `<i class="fas fa-save"></i> ${escapeHtml(i18n.t('profile.update_password'))}`;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -176,15 +171,15 @@ function renderPwRow(pw) {
|
||||
const created = document.createElement('td');
|
||||
created.textContent = new Date(pw.created_at).toLocaleDateString();
|
||||
const lastUsed = document.createElement('td');
|
||||
lastUsed.textContent = pw.last_used_at ? timeAgo(pw.last_used_at) : t('profile.never');
|
||||
lastUsed.textContent = pw.last_used_at ? timeAgo(pw.last_used_at) : i18n.t('profile.never');
|
||||
const status = document.createElement('td');
|
||||
const badge = document.createElement('span');
|
||||
if (pw.active !== false) {
|
||||
badge.className = 'badge badge-active';
|
||||
badge.textContent = t('profile.active');
|
||||
badge.textContent = i18n.t('profile.active');
|
||||
} else {
|
||||
badge.className = 'badge badge-expired';
|
||||
badge.textContent = t('profile.revoked');
|
||||
badge.textContent = i18n.t('profile.revoked');
|
||||
}
|
||||
status.appendChild(badge);
|
||||
const actions = document.createElement('td');
|
||||
@@ -192,7 +187,7 @@ function renderPwRow(pw) {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'btn btn-danger-sm';
|
||||
btn.innerHTML = '<i class="fas fa-trash"></i>';
|
||||
btn.title = t('profile.revoke_title');
|
||||
btn.title = i18n.t('profile.revoke_title');
|
||||
btn.addEventListener('click', () => {
|
||||
revokeAppPassword(pw.id, pw.label);
|
||||
});
|
||||
@@ -264,12 +259,12 @@ async function createAppPassword() {
|
||||
const btn = document.getElementById('app-pw-generate');
|
||||
|
||||
if (!label) {
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(t('profile.error_label_required'))}</div>`;
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(i18n.t('profile.error_label_required'))}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(t('profile.generating'))}`;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(i18n.t('profile.generating'))}`;
|
||||
statusEl.innerHTML = '';
|
||||
|
||||
try {
|
||||
@@ -283,7 +278,7 @@ async function createAppPassword() {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
statusEl.innerHTML =
|
||||
'<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ' +
|
||||
escapeHtml(err.message || t('profile.error_create_pw')) +
|
||||
escapeHtml(err.message || i18n.t('profile.error_create_pw')) +
|
||||
'</div>';
|
||||
return;
|
||||
}
|
||||
@@ -297,7 +292,7 @@ async function createAppPassword() {
|
||||
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${err.message}</div>`;
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = `<i class="fas fa-plus"></i> ${escapeHtml(t('profile.generate'))}`;
|
||||
btn.innerHTML = `<i class="fas fa-plus"></i> ${escapeHtml(i18n.t('profile.generate'))}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +308,7 @@ function copyAppPassword() {
|
||||
}
|
||||
|
||||
async function revokeAppPassword(id, label) {
|
||||
if (!confirm(t('profile.confirm_revoke', { label: label }))) return;
|
||||
if (!confirm(i18n.t('profile.confirm_revoke', { label: label }))) return;
|
||||
try {
|
||||
const resp = await fetch(`${API}/auth/app-passwords/${encodeURIComponent(id)}`, {
|
||||
method: 'DELETE',
|
||||
@@ -325,10 +320,10 @@ async function revokeAppPassword(id, label) {
|
||||
loadAppPasswords();
|
||||
} else {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
alert(err.message || t('profile.error_revoke'));
|
||||
alert(err.message || i18n.t('profile.error_revoke'));
|
||||
}
|
||||
} catch (err) {
|
||||
alert(t('profile.error_network', { message: err.message }));
|
||||
alert(i18n.t('profile.error_network', { message: err.message }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user