Compare commits

...

1 Commits

Author SHA1 Message Date
Admin
004cb95e56 feat(i18n): translate admin sidebar nav labels (pages + tools)
Some checks failed
CI / Backend (pull_request) Successful in 49s
CI / UI (pull_request) Failing after 23s
Release / Test backend (push) Successful in 30s
CI / Backend (push) Successful in 1m0s
CI / UI (push) Failing after 45s
Release / Check ui (push) Failing after 19s
Release / Docker / ui (push) Has been skipped
Release / Docker / caddy (push) Successful in 1m21s
Release / Docker / runner (push) Successful in 2m40s
Release / Docker / backend (push) Successful in 3m28s
Release / Gitea Release (push) Has been skipped
2026-03-31 00:42:32 +05:00
17 changed files with 282 additions and 12 deletions

View File

@@ -357,6 +357,16 @@
"admin_pages_label": "Pages",
"admin_tools_label": "Tools",
"admin_nav_scrape": "Scrape",
"admin_nav_audio": "Audio",
"admin_nav_translation": "Translation",
"admin_nav_changelog": "Changelog",
"admin_nav_feedback": "Feedback",
"admin_nav_errors": "Errors",
"admin_nav_analytics": "Analytics",
"admin_nav_logs": "Logs",
"admin_nav_uptime": "Uptime",
"admin_nav_push": "Push",
"admin_scrape_status_idle": "Idle",
"admin_scrape_status_running": "Running",

View File

@@ -357,6 +357,16 @@
"admin_pages_label": "Pages",
"admin_tools_label": "Outils",
"admin_nav_scrape": "Scrape",
"admin_nav_audio": "Audio",
"admin_nav_translation": "Traduction",
"admin_nav_changelog": "Modifications",
"admin_nav_feedback": "Retours",
"admin_nav_errors": "Erreurs",
"admin_nav_analytics": "Analytique",
"admin_nav_logs": "Journaux",
"admin_nav_uptime": "Disponibilité",
"admin_nav_push": "Notifications",
"admin_scrape_status_idle": "Inactif",
"admin_scrape_full_catalogue": "Catalogue complet",

View File

@@ -357,6 +357,16 @@
"admin_pages_label": "Halaman",
"admin_tools_label": "Alat",
"admin_nav_scrape": "Scrape",
"admin_nav_audio": "Audio",
"admin_nav_translation": "Terjemahan",
"admin_nav_changelog": "Perubahan",
"admin_nav_feedback": "Masukan",
"admin_nav_errors": "Kesalahan",
"admin_nav_analytics": "Analitik",
"admin_nav_logs": "Log",
"admin_nav_uptime": "Uptime",
"admin_nav_push": "Notifikasi",
"admin_scrape_status_idle": "Menunggu",
"admin_scrape_full_catalogue": "Katalog penuh",

View File

@@ -357,6 +357,16 @@
"admin_pages_label": "Páginas",
"admin_tools_label": "Ferramentas",
"admin_nav_scrape": "Scrape",
"admin_nav_audio": "Áudio",
"admin_nav_translation": "Tradução",
"admin_nav_changelog": "Alterações",
"admin_nav_feedback": "Feedback",
"admin_nav_errors": "Erros",
"admin_nav_analytics": "Análise",
"admin_nav_logs": "Logs",
"admin_nav_uptime": "Uptime",
"admin_nav_push": "Notificações",
"admin_scrape_status_idle": "Ocioso",
"admin_scrape_full_catalogue": "Catálogo completo",

View File

@@ -357,6 +357,16 @@
"admin_pages_label": "Страницы",
"admin_tools_label": "Инструменты",
"admin_nav_scrape": "Скрейпинг",
"admin_nav_audio": "Аудио",
"admin_nav_translation": "Перевод",
"admin_nav_changelog": "Изменения",
"admin_nav_feedback": "Отзывы",
"admin_nav_errors": "Ошибки",
"admin_nav_analytics": "Аналитика",
"admin_nav_logs": "Логи",
"admin_nav_uptime": "Мониторинг",
"admin_nav_push": "Уведомления",
"admin_scrape_status_idle": "Ожидание",
"admin_scrape_full_catalogue": "Полный каталог",

View File

@@ -328,6 +328,16 @@ export * from './user_following_label.js'
export * from './user_no_books.js'
export * from './admin_pages_label.js'
export * from './admin_tools_label.js'
export * from './admin_nav_scrape.js'
export * from './admin_nav_audio.js'
export * from './admin_nav_translation.js'
export * from './admin_nav_changelog.js'
export * from './admin_nav_feedback.js'
export * from './admin_nav_errors.js'
export * from './admin_nav_analytics.js'
export * from './admin_nav_logs.js'
export * from './admin_nav_uptime.js'
export * from './admin_nav_push.js'
export * from './admin_scrape_status_idle.js'
export * from './admin_scrape_full_catalogue.js'
export * from './admin_scrape_single_book.js'

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_AnalyticsInputs */
const en_admin_nav_analytics = () => /** @type {LocalizedString} */ (`Analytics`);
const ru_admin_nav_analytics = () => /** @type {LocalizedString} */ (`Аналитика`);
const id_admin_nav_analytics = () => /** @type {LocalizedString} */ (`Analitik`);
const pt_admin_nav_analytics = () => /** @type {LocalizedString} */ (`Análise`);
const fr_admin_nav_analytics = () => /** @type {LocalizedString} */ (`Analytique`);
export const admin_nav_analytics = /** @type {((inputs?: Admin_Nav_AnalyticsInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_AnalyticsInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_analytics(inputs)
if (locale === "ru") return ru_admin_nav_analytics(inputs)
if (locale === "id") return id_admin_nav_analytics(inputs)
if (locale === "pt") return pt_admin_nav_analytics(inputs)
return fr_admin_nav_analytics(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_AudioInputs */
const en_admin_nav_audio = () => /** @type {LocalizedString} */ (`Audio`);
const ru_admin_nav_audio = () => /** @type {LocalizedString} */ (`Аудио`);
const id_admin_nav_audio = () => /** @type {LocalizedString} */ (`Audio`);
const pt_admin_nav_audio = () => /** @type {LocalizedString} */ (`Áudio`);
const fr_admin_nav_audio = () => /** @type {LocalizedString} */ (`Audio`);
export const admin_nav_audio = /** @type {((inputs?: Admin_Nav_AudioInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_AudioInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_audio(inputs)
if (locale === "ru") return ru_admin_nav_audio(inputs)
if (locale === "id") return id_admin_nav_audio(inputs)
if (locale === "pt") return pt_admin_nav_audio(inputs)
return fr_admin_nav_audio(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_ChangelogInputs */
const en_admin_nav_changelog = () => /** @type {LocalizedString} */ (`Changelog`);
const ru_admin_nav_changelog = () => /** @type {LocalizedString} */ (`Изменения`);
const id_admin_nav_changelog = () => /** @type {LocalizedString} */ (`Perubahan`);
const pt_admin_nav_changelog = () => /** @type {LocalizedString} */ (`Alterações`);
const fr_admin_nav_changelog = () => /** @type {LocalizedString} */ (`Modifications`);
export const admin_nav_changelog = /** @type {((inputs?: Admin_Nav_ChangelogInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_ChangelogInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_changelog(inputs)
if (locale === "ru") return ru_admin_nav_changelog(inputs)
if (locale === "id") return id_admin_nav_changelog(inputs)
if (locale === "pt") return pt_admin_nav_changelog(inputs)
return fr_admin_nav_changelog(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_ErrorsInputs */
const en_admin_nav_errors = () => /** @type {LocalizedString} */ (`Errors`);
const ru_admin_nav_errors = () => /** @type {LocalizedString} */ (`Ошибки`);
const id_admin_nav_errors = () => /** @type {LocalizedString} */ (`Kesalahan`);
const pt_admin_nav_errors = () => /** @type {LocalizedString} */ (`Erros`);
const fr_admin_nav_errors = () => /** @type {LocalizedString} */ (`Erreurs`);
export const admin_nav_errors = /** @type {((inputs?: Admin_Nav_ErrorsInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_ErrorsInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_errors(inputs)
if (locale === "ru") return ru_admin_nav_errors(inputs)
if (locale === "id") return id_admin_nav_errors(inputs)
if (locale === "pt") return pt_admin_nav_errors(inputs)
return fr_admin_nav_errors(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_FeedbackInputs */
const en_admin_nav_feedback = () => /** @type {LocalizedString} */ (`Feedback`);
const ru_admin_nav_feedback = () => /** @type {LocalizedString} */ (`Отзывы`);
const id_admin_nav_feedback = () => /** @type {LocalizedString} */ (`Masukan`);
const pt_admin_nav_feedback = () => /** @type {LocalizedString} */ (`Feedback`);
const fr_admin_nav_feedback = () => /** @type {LocalizedString} */ (`Retours`);
export const admin_nav_feedback = /** @type {((inputs?: Admin_Nav_FeedbackInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_FeedbackInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_feedback(inputs)
if (locale === "ru") return ru_admin_nav_feedback(inputs)
if (locale === "id") return id_admin_nav_feedback(inputs)
if (locale === "pt") return pt_admin_nav_feedback(inputs)
return fr_admin_nav_feedback(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_LogsInputs */
const en_admin_nav_logs = () => /** @type {LocalizedString} */ (`Logs`);
const ru_admin_nav_logs = () => /** @type {LocalizedString} */ (`Логи`);
const id_admin_nav_logs = () => /** @type {LocalizedString} */ (`Log`);
const pt_admin_nav_logs = () => /** @type {LocalizedString} */ (`Logs`);
const fr_admin_nav_logs = () => /** @type {LocalizedString} */ (`Journaux`);
export const admin_nav_logs = /** @type {((inputs?: Admin_Nav_LogsInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_LogsInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_logs(inputs)
if (locale === "ru") return ru_admin_nav_logs(inputs)
if (locale === "id") return id_admin_nav_logs(inputs)
if (locale === "pt") return pt_admin_nav_logs(inputs)
return fr_admin_nav_logs(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_PushInputs */
const en_admin_nav_push = () => /** @type {LocalizedString} */ (`Push`);
const ru_admin_nav_push = () => /** @type {LocalizedString} */ (`Уведомления`);
const id_admin_nav_push = () => /** @type {LocalizedString} */ (`Notifikasi`);
const pt_admin_nav_push = () => /** @type {LocalizedString} */ (`Notificações`);
const fr_admin_nav_push = () => /** @type {LocalizedString} */ (`Notifications`);
export const admin_nav_push = /** @type {((inputs?: Admin_Nav_PushInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_PushInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_push(inputs)
if (locale === "ru") return ru_admin_nav_push(inputs)
if (locale === "id") return id_admin_nav_push(inputs)
if (locale === "pt") return pt_admin_nav_push(inputs)
return fr_admin_nav_push(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_ScrapeInputs */
const en_admin_nav_scrape = () => /** @type {LocalizedString} */ (`Scrape`);
const ru_admin_nav_scrape = () => /** @type {LocalizedString} */ (`Скрейпинг`);
const id_admin_nav_scrape = () => /** @type {LocalizedString} */ (`Scrape`);
const pt_admin_nav_scrape = () => /** @type {LocalizedString} */ (`Scrape`);
const fr_admin_nav_scrape = () => /** @type {LocalizedString} */ (`Scrape`);
export const admin_nav_scrape = /** @type {((inputs?: Admin_Nav_ScrapeInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_ScrapeInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_scrape(inputs)
if (locale === "ru") return ru_admin_nav_scrape(inputs)
if (locale === "id") return id_admin_nav_scrape(inputs)
if (locale === "pt") return pt_admin_nav_scrape(inputs)
return fr_admin_nav_scrape(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_TranslationInputs */
const en_admin_nav_translation = () => /** @type {LocalizedString} */ (`Translation`);
const ru_admin_nav_translation = () => /** @type {LocalizedString} */ (`Перевод`);
const id_admin_nav_translation = () => /** @type {LocalizedString} */ (`Terjemahan`);
const pt_admin_nav_translation = () => /** @type {LocalizedString} */ (`Tradução`);
const fr_admin_nav_translation = () => /** @type {LocalizedString} */ (`Traduction`);
export const admin_nav_translation = /** @type {((inputs?: Admin_Nav_TranslationInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_TranslationInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_translation(inputs)
if (locale === "ru") return ru_admin_nav_translation(inputs)
if (locale === "id") return id_admin_nav_translation(inputs)
if (locale === "pt") return pt_admin_nav_translation(inputs)
return fr_admin_nav_translation(inputs)
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
import { getLocale, experimentalStaticLocale } from '../runtime.js';
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
/** @typedef {{}} Admin_Nav_UptimeInputs */
const en_admin_nav_uptime = () => /** @type {LocalizedString} */ (`Uptime`);
const ru_admin_nav_uptime = () => /** @type {LocalizedString} */ (`Мониторинг`);
const id_admin_nav_uptime = () => /** @type {LocalizedString} */ (`Uptime`);
const pt_admin_nav_uptime = () => /** @type {LocalizedString} */ (`Uptime`);
const fr_admin_nav_uptime = () => /** @type {LocalizedString} */ (`Disponibilité`);
export const admin_nav_uptime = /** @type {((inputs?: Admin_Nav_UptimeInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Admin_Nav_UptimeInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
if (locale === "en") return en_admin_nav_uptime(inputs)
if (locale === "ru") return ru_admin_nav_uptime(inputs)
if (locale === "id") return id_admin_nav_uptime(inputs)
if (locale === "pt") return pt_admin_nav_uptime(inputs)
return fr_admin_nav_uptime(inputs)
});

View File

@@ -3,19 +3,19 @@
import * as m from '$lib/paraglide/messages.js';
const internalLinks = [
{ href: '/admin/scrape', label: 'Scrape' },
{ href: '/admin/audio', label: 'Audio' },
{ href: '/admin/translation', label: 'Translation' },
{ href: '/admin/changelog', label: 'Changelog' }
{ href: '/admin/scrape', label: () => m.admin_nav_scrape() },
{ href: '/admin/audio', label: () => m.admin_nav_audio() },
{ href: '/admin/translation', label: () => m.admin_nav_translation() },
{ href: '/admin/changelog', label: () => m.admin_nav_changelog() }
];
const externalLinks = [
{ href: 'https://feedback.libnovel.cc', label: 'Feedback' },
{ href: 'https://errors.libnovel.cc', label: 'Errors' },
{ href: 'https://analytics.libnovel.cc', label: 'Analytics' },
{ href: 'https://logs.libnovel.cc', label: 'Logs' },
{ href: 'https://uptime.libnovel.cc', label: 'Uptime' },
{ href: 'https://push.libnovel.cc', label: 'Push' }
{ href: 'https://feedback.libnovel.cc', label: () => m.admin_nav_feedback() },
{ href: 'https://errors.libnovel.cc', label: () => m.admin_nav_errors() },
{ href: 'https://analytics.libnovel.cc', label: () => m.admin_nav_analytics() },
{ href: 'https://logs.libnovel.cc', label: () => m.admin_nav_logs() },
{ href: 'https://uptime.libnovel.cc', label: () => m.admin_nav_uptime() },
{ href: 'https://push.libnovel.cc', label: () => m.admin_nav_push() }
];
interface Props {
@@ -39,7 +39,7 @@
? 'bg-(--color-surface-2) text-(--color-text)'
: 'text-(--color-muted) hover:bg-(--color-surface-2)/60 hover:text-(--color-text)'}"
>
{link.label}
{link.label()}
</a>
{/each}
</nav>
@@ -56,7 +56,7 @@
rel="noopener noreferrer"
class="px-2 py-1.5 rounded-md text-sm font-medium text-(--color-muted) hover:bg-(--color-surface-2)/60 hover:text-(--color-text) transition-colors flex items-center justify-between"
>
{link.label}
{link.label()}
<svg class="w-3 h-3 shrink-0 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />