mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-07-18 19:36:02 +00:00
feat(plugins): plugin system scaffold — registry tables + admin panel
First slice of the plugin system. Lays down the data model and a read-only admin surface; nothing executes yet. - Migration 155: plugins, plugin_meta_migrations, plugin_error_log and plugin_settings_fields tables. Plugin data will live in a per-plugin sqlite file under /plugins-data, never in these tables. - New Nest module server/src/nest/plugins with GET /api/admin/plugins (admin-gated, returns the installed list + the runtime-enabled flag). - TREK_PLUGINS_ENABLED kill switch (config.pluginsEnabled), off by default. - Admin → Plugins tab with a read-only panel: installed list, status badges, and a clear banner when the runtime is disabled by server config. - i18n keys for the tab and panel across all locales. Install, activation, the isolated runtime and the registry browser follow in later slices.
This commit is contained in:
@@ -460,6 +460,7 @@ export const adminApi = {
|
||||
updateOidc: (data: Record<string, unknown>) => apiClient.put('/admin/oidc', data).then(r => r.data),
|
||||
addons: () => apiClient.get('/admin/addons').then(r => r.data),
|
||||
updateAddon: (id: number | string, data: Record<string, unknown>) => apiClient.put(`/admin/addons/${id}`, data).then(r => r.data),
|
||||
plugins: () => apiClient.get('/admin/plugins').then(r => r.data),
|
||||
// Local LLM (Ollama) management for the AI-parsing addon.
|
||||
llmLocalModels: (baseUrl: string): Promise<{ models: { name: string; size: number }[] }> =>
|
||||
apiClient.get('/admin/llm/local/models', { params: { baseUrl } }).then(r => r.data),
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Blocks, AlertTriangle, PackageOpen } from 'lucide-react'
|
||||
import { adminApi } from '../../api/client'
|
||||
import { useTranslation } from '../../i18n'
|
||||
|
||||
/**
|
||||
* Admin → Plugins (#plugins), M0 read-only scaffold. Lists installed plugins
|
||||
* from the registry table and shows whether the runtime is enabled
|
||||
* (TREK_PLUGINS_ENABLED). Install, activation and the registry browser arrive in
|
||||
* later milestones; this panel is intentionally inert.
|
||||
*/
|
||||
|
||||
interface PluginRow {
|
||||
id: string
|
||||
name: string
|
||||
description: string | null
|
||||
type: string
|
||||
icon: string | null
|
||||
version: string | null
|
||||
status: string
|
||||
reviewed_at: string | null
|
||||
source_repo: string | null
|
||||
}
|
||||
|
||||
const STATUS_CLASS: Record<string, string> = {
|
||||
active: 'bg-emerald-500/15 text-emerald-600',
|
||||
inactive: 'bg-surface-tertiary text-content-muted',
|
||||
disabled: 'bg-amber-500/15 text-amber-600',
|
||||
error: 'bg-rose-500/15 text-rose-600',
|
||||
incompatible: 'bg-orange-500/15 text-orange-600',
|
||||
}
|
||||
|
||||
export default function AdminPluginsPanel() {
|
||||
const { t } = useTranslation()
|
||||
const [enabled, setEnabled] = useState(false)
|
||||
const [plugins, setPlugins] = useState<PluginRow[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
let alive = true
|
||||
adminApi.plugins()
|
||||
.then((d: { enabled: boolean; plugins: PluginRow[] }) => {
|
||||
if (!alive) return
|
||||
setEnabled(!!d.enabled)
|
||||
setPlugins(d.plugins || [])
|
||||
})
|
||||
.catch(() => { if (alive) setError(true) })
|
||||
.finally(() => { if (alive) setLoading(false) })
|
||||
return () => { alive = false }
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="bg-surface-card border border-edge rounded-xl overflow-hidden">
|
||||
<div className="px-6 py-4 border-b border-edge-secondary flex items-center gap-3">
|
||||
<div className="w-9 h-9 rounded-xl flex items-center justify-center bg-surface-tertiary">
|
||||
<Blocks size={17} className="text-content-muted" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-base font-semibold text-content">{t('admin.plugins.title')}</h2>
|
||||
<p className="text-xs text-content-faint mt-0.5">{t('admin.plugins.subtitle')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!enabled && !loading && !error && (
|
||||
<div className="mx-6 mt-4 p-4 rounded-lg border border-amber-500/30 bg-amber-500/10 flex items-start gap-3">
|
||||
<AlertTriangle size={16} className="text-amber-600 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-amber-700">{t('admin.plugins.disabledTitle')}</p>
|
||||
<p className="text-xs text-amber-700/90 mt-0.5">{t('admin.plugins.disabledBody')}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="p-6">
|
||||
{loading ? (
|
||||
<div className="py-8 text-center text-sm text-content-faint">{t('common.loading')}</div>
|
||||
) : error ? (
|
||||
<div className="py-8 text-center text-sm text-rose-600">{t('admin.plugins.loadError')}</div>
|
||||
) : plugins.length === 0 ? (
|
||||
<div className="py-10 text-center">
|
||||
<PackageOpen size={28} className="mx-auto text-content-faint mb-3" />
|
||||
<p className="text-sm text-content-muted">{t('admin.plugins.empty')}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-edge-secondary">
|
||||
{plugins.map(p => (
|
||||
<div key={p.id} className="flex items-center gap-4 py-3 first:pt-0 last:pb-0">
|
||||
<div className="w-10 h-10 rounded-xl flex items-center justify-center bg-surface-tertiary shrink-0">
|
||||
<Blocks size={16} className="text-content-muted" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-content truncate">{p.name}</span>
|
||||
{p.version && <span className="text-xs text-content-faint">v{p.version}</span>}
|
||||
</div>
|
||||
{p.description && <p className="text-xs text-content-faint truncate mt-0.5">{p.description}</p>}
|
||||
</div>
|
||||
<span className={`shrink-0 rounded-full text-[10px] font-medium px-2 py-0.5 ${STATUS_CLASS[p.status] || STATUS_CLASS.inactive}`}>
|
||||
{t(`admin.plugins.status.${p.status}` as never)}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="px-6 py-3 border-t border-edge-secondary bg-surface-secondary">
|
||||
<p className="text-xs text-content-faint">{t('admin.plugins.scaffoldNote')}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -11,7 +11,8 @@ import AddonManager from '../components/Admin/AddonManager'
|
||||
import PackingTemplateManager from '../components/Admin/PackingTemplateManager'
|
||||
import AuditLogPanel from '../components/Admin/AuditLogPanel'
|
||||
import AdminMcpTokensPanel from '../components/Admin/AdminMcpTokensPanel'
|
||||
import { Users, Map, Briefcase, Shield, FileText, SlidersHorizontal, UserCog, Puzzle, Settings as SettingsIcon, Bell, Database, ScrollText, KeyRound, GitBranch, Bug } from 'lucide-react'
|
||||
import AdminPluginsPanel from '../components/Admin/AdminPluginsPanel'
|
||||
import { Users, Map, Briefcase, Shield, FileText, SlidersHorizontal, UserCog, Puzzle, Blocks, Settings as SettingsIcon, Bell, Database, ScrollText, KeyRound, GitBranch, Bug } from 'lucide-react'
|
||||
import PageSidebar, { type PageSidebarTab } from '../components/Layout/PageSidebar'
|
||||
import { useAdmin } from './admin/useAdmin'
|
||||
import AdminUpdateBanner from './admin/AdminUpdateBanner'
|
||||
@@ -45,6 +46,7 @@ export default function AdminPage(): React.ReactElement {
|
||||
{ id: 'config', label: t('admin.tabs.config'), icon: SlidersHorizontal, group: gConfig },
|
||||
{ id: 'settings', label: t('admin.tabs.settings'), icon: SettingsIcon, group: gConfig },
|
||||
{ id: 'addons', label: t('admin.tabs.addons'), icon: Puzzle, group: gConfig },
|
||||
{ id: 'plugins', label: t('admin.tabs.plugins'), icon: Blocks, group: gConfig },
|
||||
{ id: 'notifications', label: t('admin.tabs.notifications'), icon: Bell, group: gIntegration },
|
||||
...(mcpEnabled ? [{ id: 'mcp-tokens', label: t('admin.tabs.mcpTokens'), icon: KeyRound, group: gIntegration }] : []),
|
||||
{ id: 'github', label: t('admin.tabs.github'), icon: GitBranch, group: gIntegration },
|
||||
@@ -157,6 +159,8 @@ export default function AdminPage(): React.ReactElement {
|
||||
|
||||
{activeTab === 'mcp-tokens' && <AdminMcpTokensPanel />}
|
||||
|
||||
{activeTab === 'plugins' && <AdminPluginsPanel />}
|
||||
|
||||
{activeTab === 'github' && <GitHubPanel isPrerelease={updateInfo?.is_prerelease ?? false} />}
|
||||
|
||||
{activeTab === 'defaults' && <DefaultUserSettingsTab />}
|
||||
|
||||
@@ -174,3 +174,14 @@ export const SESSION_DURATION_REMEMBER =
|
||||
export const SESSION_DURATION_REMEMBER_MS = parsedRememberMs ?? parseDurationMs(DEFAULT_SESSION_DURATION_REMEMBER)!;
|
||||
/** "Remember me" session length in seconds — passed to `jwt.sign({ expiresIn })`. */
|
||||
export const SESSION_DURATION_REMEMBER_SECONDS = Math.floor(SESSION_DURATION_REMEMBER_MS / 1000);
|
||||
|
||||
/**
|
||||
* Plugin-system kill switch (#plugins). Off by default — a brand-new, high-risk
|
||||
* surface an instance owner must deliberately opt into. When false, the plugin
|
||||
* module serves its admin listing (so the tab isn't a dead end) but never spawns
|
||||
* a plugin process and refuses install/activate. Read at call time so tests and
|
||||
* runtime env changes take effect without re-import.
|
||||
*/
|
||||
export function pluginsEnabled(): boolean {
|
||||
return (process.env.TREK_PLUGINS_ENABLED || '').trim().toLowerCase() === 'true';
|
||||
}
|
||||
|
||||
@@ -3289,6 +3289,69 @@ function runMigrations(db: Database.Database): void {
|
||||
() => {
|
||||
try { db.exec('ALTER TABLE invite_tokens ADD COLUMN trip_id INTEGER REFERENCES trips(id) ON DELETE SET NULL'); } catch (err) { console.warn('[migrations] Non-fatal migration step failed:', err); }
|
||||
},
|
||||
// Migration 155: plugin system scaffold (#plugins). A plugin is a row here;
|
||||
// its code lives on the /plugins volume and (once the runtime lands) runs in
|
||||
// an isolated child process. This migration only lays down the registry
|
||||
// tables — nothing executes yet. Own data lives in a per-plugin sqlite file
|
||||
// under /plugins-data, never in these tables.
|
||||
() => {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS plugins (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'integration',
|
||||
icon TEXT DEFAULT 'Blocks',
|
||||
version TEXT,
|
||||
api_version INTEGER DEFAULT 1,
|
||||
min_trek_version TEXT,
|
||||
permissions TEXT DEFAULT '[]',
|
||||
granted_permissions TEXT DEFAULT '[]',
|
||||
status TEXT NOT NULL DEFAULT 'inactive',
|
||||
config TEXT DEFAULT '{}',
|
||||
source_repo TEXT,
|
||||
source_commit TEXT,
|
||||
sha256 TEXT,
|
||||
crash_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
reviewed_at TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
installed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS plugin_meta_migrations (
|
||||
plugin_id TEXT NOT NULL,
|
||||
migration_id TEXT NOT NULL,
|
||||
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (plugin_id, migration_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS plugin_error_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
plugin_id TEXT NOT NULL,
|
||||
ts DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
level TEXT NOT NULL DEFAULT 'error',
|
||||
message TEXT,
|
||||
stack TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_plugin_error_log_plugin ON plugin_error_log(plugin_id, ts);
|
||||
CREATE TABLE IF NOT EXISTS plugin_settings_fields (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
plugin_id TEXT NOT NULL,
|
||||
field_key TEXT NOT NULL,
|
||||
label TEXT,
|
||||
input_type TEXT NOT NULL DEFAULT 'text',
|
||||
placeholder TEXT,
|
||||
hint TEXT,
|
||||
required INTEGER NOT NULL DEFAULT 0,
|
||||
secret INTEGER NOT NULL DEFAULT 0,
|
||||
scope TEXT NOT NULL DEFAULT 'instance',
|
||||
options TEXT,
|
||||
oauth_config TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
UNIQUE (plugin_id, field_key)
|
||||
);
|
||||
`);
|
||||
},
|
||||
];
|
||||
|
||||
if (currentVersion < migrations.length) {
|
||||
|
||||
@@ -41,6 +41,7 @@ import { OidcModule } from './oidc/oidc.module';
|
||||
import { OauthModule } from './oauth/oauth.module';
|
||||
import { AdminModule } from './admin/admin.module';
|
||||
import { AddonsModule } from './addons/addons.module';
|
||||
import { PluginsModule } from './plugins/plugins.module';
|
||||
import { TrekExceptionFilter } from './common/trek-exception.filter';
|
||||
import { SpaFallbackFilter } from './platform/spa-fallback.filter';
|
||||
import { IdempotencyInterceptor } from './common/idempotency.interceptor';
|
||||
@@ -51,7 +52,7 @@ import { IdempotencyInterceptor } from './common/idempotency.interceptor';
|
||||
* migrated.
|
||||
*/
|
||||
@Module({
|
||||
imports: [DatabaseModule, WeatherModule, HelpModule, AirportsModule, ConfigModule, SystemNoticesModule, MapsModule, CategoriesModule, TagsModule, NotificationsModule, AtlasModule, VacayModule, PackingModule, TodoModule, BudgetModule, ReservationsModule, DaysModule, AssignmentsModule, PlacesModule, TripsModule, CollabModule, FilesModule, PhotosModule, MemoriesModule, AirtrailModule, JourneyModule, CollectionsModule, ShareModule, TripInviteModule, TransitModule, FeedsModule, SettingsModule, BackupModule, AuthModule, OidcModule, OauthModule, AdminModule, AddonsModule, BookingImportModule],
|
||||
imports: [DatabaseModule, WeatherModule, HelpModule, AirportsModule, ConfigModule, SystemNoticesModule, MapsModule, CategoriesModule, TagsModule, NotificationsModule, AtlasModule, VacayModule, PackingModule, TodoModule, BudgetModule, ReservationsModule, DaysModule, AssignmentsModule, PlacesModule, TripsModule, CollabModule, FilesModule, PhotosModule, MemoriesModule, AirtrailModule, JourneyModule, CollectionsModule, ShareModule, TripInviteModule, TransitModule, FeedsModule, SettingsModule, BackupModule, AuthModule, OidcModule, OauthModule, AdminModule, AddonsModule, PluginsModule, BookingImportModule],
|
||||
controllers: [HealthController],
|
||||
providers: [
|
||||
HealthService,
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Controller, Get, UseGuards } from '@nestjs/common';
|
||||
import { PluginsService } from './plugins.service';
|
||||
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
|
||||
import { AdminGuard } from '../auth/admin.guard';
|
||||
|
||||
/**
|
||||
* /api/admin/plugins — admin-only plugin control surface (#plugins).
|
||||
*
|
||||
* M0 scaffold: read-only listing + the runtime-enabled flag. Install, activate,
|
||||
* disable, uninstall and the registry browser are added in later milestones.
|
||||
* Admin-gated like the rest of /api/admin. The proxy namespace /api/plugins/:id
|
||||
* is reserved for the (future) runtime and is intentionally NOT part of this
|
||||
* admin controller.
|
||||
*/
|
||||
@Controller('api/admin/plugins')
|
||||
@UseGuards(JwtAuthGuard, AdminGuard)
|
||||
export class PluginsController {
|
||||
constructor(private readonly plugins: PluginsService) {}
|
||||
|
||||
@Get()
|
||||
list() {
|
||||
return this.plugins.list();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PluginsController } from './plugins.controller';
|
||||
import { PluginsService } from './plugins.service';
|
||||
|
||||
/**
|
||||
* Plugin system (#plugins). M0 registers only the read side; the isolated
|
||||
* runtime supervisor, install pipeline and registry service are added in later
|
||||
* milestones under this same module.
|
||||
*/
|
||||
@Module({
|
||||
controllers: [PluginsController],
|
||||
providers: [PluginsService],
|
||||
})
|
||||
export class PluginsModule {}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { db } from '../../db/database';
|
||||
import { pluginsEnabled } from '../../config';
|
||||
|
||||
/**
|
||||
* Read side of the plugin system (#plugins), M0 scaffold. Lists installed
|
||||
* plugins from the `plugins` registry table and reports whether the runtime is
|
||||
* enabled (TREK_PLUGINS_ENABLED). No execution here — the isolated runtime,
|
||||
* install pipeline and registry fetch land in later milestones.
|
||||
*/
|
||||
|
||||
export interface PluginListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
type: string;
|
||||
icon: string | null;
|
||||
version: string | null;
|
||||
status: string;
|
||||
reviewed_at: string | null;
|
||||
source_repo: string | null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PluginsService {
|
||||
list(): { enabled: boolean; plugins: PluginListItem[] } {
|
||||
const plugins = db
|
||||
.prepare(
|
||||
`SELECT id, name, description, type, icon, version, status, reviewed_at, source_repo
|
||||
FROM plugins
|
||||
ORDER BY sort_order, name`,
|
||||
)
|
||||
.all() as PluginListItem[];
|
||||
return { enabled: pluginsEnabled(), plugins };
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'فشل حذف القالب',
|
||||
'admin.packingTemplates.saveError': 'فشل الحفظ',
|
||||
'admin.tabs.addons': 'الإضافات',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'الإضافات',
|
||||
'admin.addons.subtitle': 'فعّل أو عطّل الميزات لتخصيص تجربة TREK.',
|
||||
'admin.addons.catalog.packing.name': 'القوائم',
|
||||
|
||||
@@ -156,6 +156,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Falha ao excluir modelo',
|
||||
'admin.packingTemplates.saveError': 'Falha ao salvar',
|
||||
'admin.tabs.addons': 'Complementos',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Complementos',
|
||||
'admin.addons.subtitle': 'Ative ou desative recursos para personalizar sua experiência no TREK.',
|
||||
'admin.addons.catalog.memories.name': 'Memórias',
|
||||
|
||||
@@ -157,6 +157,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Nepodařilo se smazat šablonu',
|
||||
'admin.packingTemplates.saveError': 'Uložení se nezdařilo',
|
||||
'admin.tabs.addons': 'Doplňky',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Doplňky',
|
||||
'admin.addons.subtitle': 'Zapněte nebo vypněte funkce a přizpůsobte si TREK.',
|
||||
'admin.addons.catalog.memories.name': 'Fotky (Immich)',
|
||||
|
||||
@@ -159,6 +159,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Vorlage konnte nicht gelöscht werden',
|
||||
'admin.packingTemplates.saveError': 'Fehler beim Speichern',
|
||||
'admin.tabs.addons': 'Addons',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Plugins von Drittanbietern auf deiner Instanz installieren und verwalten.',
|
||||
'admin.plugins.disabledTitle': 'Plugins sind deaktiviert',
|
||||
'admin.plugins.disabledBody': 'Die Plugin-Laufzeit ist ausgeschaltet (TREK_PLUGINS_ENABLED). Es kann kein Plugin laufen, bis ein Admin sie in der Serverkonfiguration aktiviert.',
|
||||
'admin.plugins.empty': 'Noch keine Plugins installiert.',
|
||||
'admin.plugins.loadError': 'Plugins konnten nicht geladen werden.',
|
||||
'admin.plugins.scaffoldNote': 'Installation und Aktivierung von Plugins folgen in einem späteren Update. Dieses Panel zeigt derzeit nur installierte Plugins an.',
|
||||
'admin.plugins.status.active': 'Aktiv',
|
||||
'admin.plugins.status.inactive': 'Inaktiv',
|
||||
'admin.plugins.status.disabled': 'Deaktiviert',
|
||||
'admin.plugins.status.error': 'Fehler',
|
||||
'admin.plugins.status.incompatible': 'Inkompatibel',
|
||||
'admin.addons.title': 'Addons',
|
||||
'admin.addons.subtitle': 'Aktiviere oder deaktiviere Funktionen, um TREK nach deinen Wünschen anzupassen.',
|
||||
'admin.addons.catalog.packing.name': 'Listen',
|
||||
|
||||
@@ -211,6 +211,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Failed to delete template',
|
||||
'admin.packingTemplates.saveError': 'Failed to save',
|
||||
'admin.tabs.addons': 'Addons',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Addons',
|
||||
'admin.addons.subtitle': 'Enable or disable features to customize your TREK experience.',
|
||||
'admin.addons.catalog.packing.name': 'Lists',
|
||||
|
||||
@@ -158,6 +158,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Error al eliminar plantilla',
|
||||
'admin.packingTemplates.saveError': 'Error al guardar',
|
||||
'admin.tabs.addons': 'Complementos',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Complementos',
|
||||
'admin.addons.subtitle': 'Activa o desactiva funciones para personalizar tu experiencia en TREK.',
|
||||
'admin.addons.subtitleBefore': 'Activa o desactiva funciones para personalizar tu experiencia en ',
|
||||
|
||||
@@ -160,6 +160,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Erreur de suppression du modèle',
|
||||
'admin.packingTemplates.saveError': 'Erreur de sauvegarde',
|
||||
'admin.tabs.addons': 'Extensions',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Extensions',
|
||||
'admin.addons.subtitle': 'Activez ou désactivez des fonctionnalités pour personnaliser votre expérience TREK.',
|
||||
'admin.addons.catalog.memories.name': 'Photos (Immich)',
|
||||
|
||||
@@ -205,6 +205,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Αποτυχία διαγραφής προτύπου',
|
||||
'admin.packingTemplates.saveError': 'Αποτυχία αποθήκευσης',
|
||||
'admin.tabs.addons': 'Πρόσθετα',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Πρόσθετα',
|
||||
'admin.addons.subtitle':
|
||||
'Ενεργοποιήστε ή απενεργοποιήστε λειτουργίες για να εξατομικεύσετε την εμπειρία σας στο TREK.',
|
||||
|
||||
@@ -159,6 +159,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Nem sikerült törölni a sablont',
|
||||
'admin.packingTemplates.saveError': 'Nem sikerült menteni',
|
||||
'admin.tabs.addons': 'Bővítmények',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Bővítmények',
|
||||
'admin.addons.subtitle': 'Funkciók engedélyezése vagy letiltása a TREK testreszabásához.',
|
||||
'admin.addons.catalog.packing.name': 'Listák',
|
||||
|
||||
@@ -201,6 +201,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Gagal menghapus template',
|
||||
'admin.packingTemplates.saveError': 'Gagal menyimpan',
|
||||
'admin.tabs.addons': 'Addon',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Addon',
|
||||
'admin.addons.subtitle': 'Aktifkan atau nonaktifkan fitur untuk menyesuaikan pengalaman TREK kamu.',
|
||||
'admin.addons.catalog.packing.name': 'Daftar',
|
||||
|
||||
@@ -158,6 +158,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Impossibile eliminare il modello',
|
||||
'admin.packingTemplates.saveError': 'Impossibile salvare',
|
||||
'admin.tabs.addons': 'Moduli',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Moduli',
|
||||
'admin.addons.subtitle': 'Abilita o disabilita le funzionalità per personalizzare la tua esperienza TREK.',
|
||||
'admin.addons.catalog.packing.name': 'Liste',
|
||||
|
||||
@@ -190,6 +190,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'テンプレートの削除に失敗しました',
|
||||
'admin.packingTemplates.saveError': '保存に失敗しました',
|
||||
'admin.tabs.addons': 'アドオン',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'アドオン',
|
||||
'admin.addons.subtitle': '機能を有効/無効にしてTREKをカスタマイズします。',
|
||||
'admin.addons.catalog.packing.name': 'リスト',
|
||||
|
||||
@@ -196,6 +196,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': '템플릿 삭제 실패',
|
||||
'admin.packingTemplates.saveError': '저장 실패',
|
||||
'admin.tabs.addons': '애드온',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': '애드온',
|
||||
'admin.addons.subtitle': '기능을 활성화 또는 비활성화하여 TREK 경험을 맞춤 설정하세요.',
|
||||
'admin.addons.catalog.packing.name': '목록',
|
||||
|
||||
@@ -159,6 +159,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Fout bij verwijderen van sjabloon',
|
||||
'admin.packingTemplates.saveError': 'Fout bij opslaan',
|
||||
'admin.tabs.addons': 'Add-ons',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Add-ons',
|
||||
'admin.addons.subtitle': 'Schakel functies in of uit om je TREK-ervaring aan te passen.',
|
||||
'admin.addons.catalog.memories.name': "Foto's (Immich)",
|
||||
|
||||
@@ -152,6 +152,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Nie udało się usunąć szablonu',
|
||||
'admin.packingTemplates.saveError': 'Nie udało się zapisać szablonu',
|
||||
'admin.tabs.addons': 'Dodatki',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Dodatki',
|
||||
'admin.addons.subtitle': 'Włączaj lub wyłączaj funkcje, aby dostosować swoje doświadczenie w TREK.',
|
||||
'admin.addons.catalog.packing.name': 'Listy',
|
||||
|
||||
@@ -159,6 +159,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Ошибка удаления шаблона',
|
||||
'admin.packingTemplates.saveError': 'Ошибка сохранения',
|
||||
'admin.tabs.addons': 'Дополнения',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Дополнения',
|
||||
'admin.addons.subtitle': 'Включайте или отключайте функции для настройки TREK под себя.',
|
||||
'admin.addons.catalog.memories.name': 'Фото (Immich)',
|
||||
|
||||
@@ -211,6 +211,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Det gick inte att ta bort mallen',
|
||||
'admin.packingTemplates.saveError': 'Det gick inte att spara',
|
||||
'admin.tabs.addons': 'Tillägg',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Tillägg',
|
||||
'admin.addons.subtitle': 'Aktivera eller inaktivera funktioner för att anpassa din TREK-upplevelse.',
|
||||
'admin.addons.catalog.packing.name': 'Listor',
|
||||
|
||||
@@ -203,6 +203,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Şablon silinemedi',
|
||||
'admin.packingTemplates.saveError': 'Kaydedilemedi',
|
||||
'admin.tabs.addons': 'Eklentiler',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Eklentiler',
|
||||
'admin.addons.subtitle': 'TREK deneyiminizi özelleştirmek için özellikleri etkinleştirin veya devre dışı bırakın.',
|
||||
'admin.addons.catalog.packing.name': 'Listeler',
|
||||
|
||||
@@ -159,6 +159,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Помилка видалення шаблону',
|
||||
'admin.packingTemplates.saveError': 'Помилка збереження',
|
||||
'admin.tabs.addons': 'Дополнения',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Доповнення',
|
||||
'admin.addons.subtitle': 'Увімкніть або вимкніть функції, щоб налаштувати TREK під себе.',
|
||||
'admin.addons.catalog.memories.name': 'Фото (Immich)',
|
||||
|
||||
@@ -211,6 +211,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': 'Không xóa được mẫu',
|
||||
'admin.packingTemplates.saveError': 'Không lưu được',
|
||||
'admin.tabs.addons': 'Tiện ích bổ sung',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': 'Tiện ích bổ sung',
|
||||
'admin.addons.subtitle': 'Bật hoặc tắt các tính năng để tùy chỉnh trải nghiệm TREK của bạn.',
|
||||
'admin.addons.catalog.packing.name': 'Danh sách',
|
||||
|
||||
@@ -193,6 +193,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': '刪除模板失敗',
|
||||
'admin.packingTemplates.saveError': '儲存失敗',
|
||||
'admin.tabs.addons': '擴充套件',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': '擴充套件',
|
||||
'admin.addons.subtitle': '啟用或停用功能以自定義你的 TREK 體驗。',
|
||||
'admin.addons.catalog.memories.name': '照片 (Immich)',
|
||||
|
||||
@@ -154,6 +154,19 @@ const admin: TranslationStrings = {
|
||||
'admin.packingTemplates.deleteError': '删除模板失败',
|
||||
'admin.packingTemplates.saveError': '保存失败',
|
||||
'admin.tabs.addons': '扩展',
|
||||
'admin.tabs.plugins': 'Plugins',
|
||||
'admin.plugins.title': 'Plugins',
|
||||
'admin.plugins.subtitle': 'Install and manage third-party plugins on your instance.',
|
||||
'admin.plugins.disabledTitle': 'Plugins are disabled',
|
||||
'admin.plugins.disabledBody': 'The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.',
|
||||
'admin.plugins.empty': 'No plugins installed yet.',
|
||||
'admin.plugins.loadError': 'Could not load plugins.',
|
||||
'admin.plugins.scaffoldNote': 'Plugin installation and activation are coming in a later update. This panel currently lists installed plugins only.',
|
||||
'admin.plugins.status.active': 'Active',
|
||||
'admin.plugins.status.inactive': 'Inactive',
|
||||
'admin.plugins.status.disabled': 'Disabled',
|
||||
'admin.plugins.status.error': 'Error',
|
||||
'admin.plugins.status.incompatible': 'Incompatible',
|
||||
'admin.addons.title': '扩展',
|
||||
'admin.addons.subtitle': '启用或禁用功能以自定义你的 TREK 体验。',
|
||||
'admin.addons.catalog.memories.name': '照片 (Immich)',
|
||||
|
||||
Reference in New Issue
Block a user