Compare commits

..

13 Commits

Author SHA1 Message Date
Shift
b263a80b70 composer update 2026-07-21 16:44:38 +00:00
Shift
a62482beeb Bump Laravel version constraint 2026-07-21 16:42:34 +00:00
Boy132
7d9400f023 Fix backup hosts migration (#2468) 2026-07-21 09:17:14 +02:00
Boy132
79ad59dbc3 Fix bulk delete label (#2469) 2026-07-21 09:16:55 +02:00
github-actions[bot]
880f20b2cf New Crowdin Translations (#2466) 2026-07-18 20:37:10 -04:00
Lance Pioch
b1dd8d93f5 Fix flaky allocation test (#2465) 2026-07-18 12:39:03 -04:00
Boy132
21d125d905 Cleanup, fix and expand various relation managers and lists (#2456) 2026-07-18 14:49:41 +02:00
Boy132
b9f0eff6b2 Do not throw exception when trying to delete a failed backup (#2458) 2026-07-17 09:42:26 +02:00
Boy132
5b6f497863 Add interface function to auto fill plugin settings form (#2453) 2026-07-17 08:49:34 +02:00
Boy132
d2dc6b69c8 Add authorize check to egg feature modals (#2459) 2026-07-17 08:35:58 +02:00
Boy132
2b34cc4d3c Fix navigation groups (#2455) 2026-07-17 08:34:29 +02:00
Dmytro Pashchenko
c6d777f25d Add DB_SCHEMA support for PostgreSQL connections (#2449) 2026-07-16 20:34:57 -04:00
Lance Pioch
4950bbd06e Laravel 13.20.0 Shift (#2454)
Co-authored-by: Shift <shift@laravelshift.com>
2026-07-16 20:27:21 -04:00
144 changed files with 3495 additions and 999 deletions

View File

@@ -24,6 +24,7 @@ class DatabaseSettingsCommand extends Command
protected $signature = 'p:environment:database
{--driver= : The database driver backend to use.}
{--database= : The database to use.}
{--schema= : The schema to use for the PostgreSQL database.}
{--host= : The connection address for the MySQL/ MariaDB/ PostgreSQL server.}
{--port= : The connection port for the MySQL/ MariaDB/ PostgreSQL server.}
{--username= : Username to use when connecting to the MySQL/ MariaDB/ PostgreSQL server.}
@@ -196,6 +197,11 @@ class DatabaseSettingsCommand extends Command
config('database.connections.pgsql.database', 'panel')
);
$this->variables['DB_SCHEMA'] = $this->option('schema') ?? $this->ask(
'Database Schema',
config('database.connections.pgsql.search_path', 'public')
);
$this->output->note(trans('commands.database_settings.DB_USERNAME_note'));
$this->variables['DB_USERNAME'] = $this->option('username') ?? $this->ask(
'Database Username',
@@ -224,7 +230,7 @@ class DatabaseSettingsCommand extends Command
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'search_path' => $this->variables['DB_SCHEMA'],
'sslmode' => 'prefer',
]);

View File

@@ -6,6 +6,11 @@ use Filament\Schemas\Components\Component;
interface HasPluginSettings
{
/**
* @return array<string, mixed>
*/
public function getSettingsFormData(): array;
/**
* @return Component[]
*/

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Enums;
enum ServerUserSettingKey: string
{
case ManualBackupNotifications = 'manual_backup_notifications';
case ScheduledBackupNotifications = 'scheduled_backup_notifications';
/**
* The default value for users without an explicit setting.
*/
public function getDefaultValue(): bool
{
return match ($this) {
self::ManualBackupNotifications, self::ScheduledBackupNotifications => false,
};
}
/** @return array<string, bool> */
public static function getDefaultSettings(): array
{
$default = [];
foreach (self::cases() as $key) {
$default[$key->value] = $key->getDefaultValue();
}
return $default;
}
}

View File

@@ -2,6 +2,8 @@
namespace App\Extensions\Features;
use App\Models\Server;
use App\Models\User;
use Filament\Actions\Action;
interface FeatureSchemaInterface
@@ -11,5 +13,7 @@ interface FeatureSchemaInterface
public function getId(): string;
public function authorize(User $user, Server $server): bool;
public function getAction(): Action;
}

View File

@@ -8,6 +8,7 @@ use App\Extensions\Features\FeatureSchemaInterface;
use App\Facades\Activity;
use App\Models\Server;
use App\Models\ServerVariable;
use App\Models\User;
use App\Repositories\Daemon\DaemonServerRepository;
use Closure;
use Exception;
@@ -37,6 +38,11 @@ class GSLTokenSchema implements FeatureSchemaInterface
return 'gsl_token';
}
public function authorize(User $user, Server $server): bool
{
return $user->can(SubuserPermission::StartupUpdate, $server);
}
/**
* @throws Exception
*/
@@ -55,7 +61,6 @@ class GSLTokenSchema implements FeatureSchemaInterface
->modalHeading(trans('server/feature.gsl_token.heading'))
->modalDescription(trans('server/feature.gsl_token.description'))
->modalSubmitActionLabel(trans('server/feature.gsl_token.submit'))
->disabledSchema(fn () => !user()?->can(SubuserPermission::StartupUpdate, $server))
->schema([
TextEntry::make('info')
->label(new HtmlString(Blade::render(trans('server/feature.gsl_token.info')))),

View File

@@ -6,6 +6,7 @@ use App\Enums\SubuserPermission;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Facades\Activity;
use App\Models\Server;
use App\Models\User;
use App\Repositories\Daemon\DaemonServerRepository;
use Exception;
use Filament\Actions\Action;
@@ -34,6 +35,11 @@ class JavaVersionSchema implements FeatureSchemaInterface
return 'java_version';
}
public function authorize(User $user, Server $server): bool
{
return $user->can(SubuserPermission::StartupDockerImage, $server);
}
public function getAction(): Action
{
/** @var Server $server */
@@ -44,7 +50,6 @@ class JavaVersionSchema implements FeatureSchemaInterface
->modalHeading(trans('server/feature.java_version.heading'))
->modalDescription(trans('server/feature.java_version.description'))
->modalSubmitActionLabel(trans('server/feature.java_version.submit'))
->disabledSchema(fn () => !user()?->can(SubuserPermission::StartupDockerImage, $server))
->schema([
TextEntry::make('java')
->label(trans('server/feature.java_version.select_version')),

View File

@@ -2,8 +2,10 @@
namespace App\Extensions\Features\Schemas;
use App\Enums\SubuserPermission;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Models\Server;
use App\Models\User;
use App\Repositories\Daemon\DaemonFileRepository;
use App\Repositories\Daemon\DaemonServerRepository;
use Exception;
@@ -28,6 +30,11 @@ class MinecraftEulaSchema implements FeatureSchemaInterface
return 'eula';
}
public function authorize(User $user, Server $server): bool
{
return $user->can(SubuserPermission::FileUpdate, $server);
}
public function getAction(): Action
{
return Action::make($this->getId())

View File

@@ -4,6 +4,8 @@ namespace App\Extensions\Features\Schemas;
use App\Enums\TablerIcon;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Models\Server;
use App\Models\User;
use Filament\Actions\Action;
use Illuminate\Support\HtmlString;
@@ -27,6 +29,11 @@ class PIDLimitSchema implements FeatureSchemaInterface
return 'pid_limit';
}
public function authorize(User $user, Server $server): bool
{
return true;
}
public function getAction(): Action
{
return Action::make($this->getId())

View File

@@ -3,6 +3,8 @@
namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Models\Server;
use App\Models\User;
use Filament\Actions\Action;
use Illuminate\Support\HtmlString;
@@ -22,6 +24,11 @@ class SteamDiskSpaceSchema implements FeatureSchemaInterface
return 'steam_disk_space';
}
public function authorize(User $user, Server $server): bool
{
return true;
}
public function getAction(): Action
{
return Action::make($this->getId())

View File

@@ -17,7 +17,7 @@ final class CreateBackupSchema extends TaskSchema
public function runTask(Task $task): void
{
$this->initiateService->setIsScheduled(true)->setIgnoredFiles(explode(PHP_EOL, $task->payload))->handle($task->server, null, true);
$this->initiateService->setIgnoredFiles(explode(PHP_EOL, $task->payload))->handle($task->server, null, true);
}
public function canCreate(Schedule $schedule): bool

View File

@@ -689,6 +689,16 @@ class Settings extends Page implements HasSchemas
->formatStateUsing(fn ($state): bool => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('PANEL_SEND_REINSTALL_NOTIFICATION', (bool) $state))
->default(env('PANEL_SEND_REINSTALL_NOTIFICATION', config('panel.email.send_reinstall_notification'))),
Toggle::make('PANEL_SEND_BACKUP_COMPLETED_NOTIFICATION')
->label(trans('admin/setting.misc.mail_notifications.backup_completed'))
->onIcon(TablerIcon::Check)
->offIcon(TablerIcon::X)
->onColor('success')
->offColor('danger')
->live()
->formatStateUsing(fn ($state): bool => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('PANEL_SEND_BACKUP_COMPLETED_NOTIFICATION', (bool) $state))
->default(env('PANEL_SEND_BACKUP_COMPLETED_NOTIFICATION', config('panel.email.send_backup_completed_notification'))),
]),
Section::make(trans('admin/setting.misc.connections.title'))
->description(trans('admin/setting.misc.connections.helper'))

View File

@@ -2,6 +2,7 @@
namespace App\Filament\Admin\Resources\DatabaseHosts\RelationManagers;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Components\Actions\RotateDatabasePasswordAction;
use App\Filament\Components\Tables\Columns\DateTimeColumn;
use App\Models\Database;
@@ -50,7 +51,7 @@ class DatabasesRelationManager extends RelationManager
{
return $table
->recordTitleAttribute('database')
->heading('')
->heading(null)
->columns([
TextColumn::make('database'),
TextColumn::make('username')
@@ -59,7 +60,7 @@ class DatabasesRelationManager extends RelationManager
->label(trans('admin/databasehost.table.remote'))
->formatStateUsing(fn (Database $record) => $record->remote === '%' ? trans('admin/databasehost.anywhere'). ' ( % )' : $record->remote),
TextColumn::make('server.name')
->url(fn (Database $database) => route('filament.admin.resources.servers.edit', ['record' => $database->server_id])),
->url(fn (Database $database) => user()?->can('update', $database->server) ? EditServer::getUrl(['record' => $database->server]) : null),
TextColumn::make('max_connections')
->label(trans('admin/databasehost.table.max_connections'))
->formatStateUsing(fn ($record) => $record->max_connections ?: trans('server/database.unlimited')),

View File

@@ -34,7 +34,7 @@ class EggResource extends Resource
public static function getNavigationGroup(): ?string
{
if (user()?->getCustomization(CustomizationKey::TopNavigation)) {
if (user()?->getCustomization(CustomizationKey::TopNavigation) === 'topbar') {
return null;
}

View File

@@ -43,12 +43,8 @@ class ListEggs extends ListRecords
$defaultEggIcon = 'data:image/svg+xml;base64,' . base64_encode(file_get_contents(public_path($defaultEggIcon)));
return $table
->searchable(true)
->defaultPaginationPageOption(25)
->columns([
TextColumn::make('id')
->label('Id')
->hidden(),
ImageColumn::make('icon')
->label('')
->alignCenter()
@@ -56,7 +52,7 @@ class ListEggs extends ListRecords
->getStateUsing(fn (Egg $record) => $record->icon ?: $defaultEggIcon),
TextColumn::make('name')
->label(trans('admin/egg.name'))
->description(fn ($record): ?string => (strlen($record->description) > 120) ? substr($record->description, 0, 120).'...' : $record->description)
->description(fn ($record) => (strlen($record->description) > 120) ? substr($record->description, 0, 120).'...' : $record->description)
->wrap()
->searchable()
->sortable(),

View File

@@ -2,9 +2,13 @@
namespace App\Filament\Admin\Resources\Eggs\RelationManagers;
use App\Filament\Admin\Resources\Nodes\Pages\EditNode;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Admin\Resources\Users\Pages\EditUser;
use App\Filament\Components\Actions\ViewConsoleAction;
use App\Models\Server;
use Filament\Actions\EditAction;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
@@ -18,27 +22,35 @@ class ServersRelationManager extends RelationManager
->recordTitleAttribute('servers')
->emptyStateDescription(trans('admin/egg.no_servers'))
->emptyStateHeading(trans('admin/egg.no_servers_help'))
->searchable(false)
->heading(trans('admin/egg.servers'))
->columns([
TextColumn::make('user.username')
->label(trans('admin/server.owner'))
->url(fn (Server $server): string => route('filament.admin.resources.users.edit', ['record' => $server->user]))
->sortable(),
->url(fn (Server $server) => user()?->can('update', $server->user) ? EditUser::getUrl(['record' => $server->user]) : null)
->sortable()
->searchable(),
TextColumn::make('name')
->label(trans('admin/server.name'))
->url(fn (Server $server): string => route('filament.admin.resources.servers.edit', ['record' => $server]))
->sortable(),
->url(fn (Server $server) => user()?->can('update', $server) ? EditServer::getUrl(['record' => $server]) : null)
->sortable()
->searchable(),
TextColumn::make('node.name')
->url(fn (Server $server): string => route('filament.admin.resources.nodes.edit', ['record' => $server->node])),
->label(trans('admin/server.node'))
->url(fn (Server $server) => user()?->can('update', $server->node) ? EditNode::getUrl(['record' => $server->node]) : null)
->sortable()
->searchable(),
TextColumn::make('image')
->label(trans('admin/server.docker_image')),
SelectColumn::make('allocation.id')
->label(trans('admin/server.docker_image'))
->badge(),
TextColumn::make('allocation.address')
->label(trans('admin/server.primary_allocation'))
->disabled()
->options(fn (Server $server) => $server->allocations->take(1)->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address]))
->placeholder(trans('admin/server.none'))
->sortable(),
])
->recordActions([
ViewConsoleAction::make(),
EditAction::make()
->url(fn (Server $server) => EditServer::getUrl(['record' => $server], panel: 'admin')),
]);
}
}

View File

@@ -46,7 +46,7 @@ class NodeResource extends Resource
public static function getNavigationGroup(): ?string
{
if (user()?->getCustomization(CustomizationKey::TopNavigation)) {
if (user()?->getCustomization(CustomizationKey::TopNavigation) === 'topbar') {
return null;
}

View File

@@ -27,7 +27,6 @@ class ListNodes extends ListRecords
public function table(Table $table): Table
{
return $table
->searchable(false)
->checkIfRecordIsSelectableUsing(fn (Node $node) => $node->servers_count <= 0)
->columns([
TextColumn::make('uuid')

View File

@@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\Nodes\RelationManagers;
use App\Enums\TablerIcon;
use App\Filament\Admin\Resources\Servers\Pages\CreateServer;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Components\Actions\UpdateNodeAllocations;
use App\Models\Allocation;
use App\Models\Node;
@@ -11,6 +12,8 @@ use App\Services\Allocations\AssignmentService;
use BackedEnum;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TagsInput;
@@ -30,7 +33,7 @@ class AllocationsRelationManager extends RelationManager
{
protected static string $relationship = 'allocations';
protected static string|BackedEnum|null $icon = TablerIcon::PlugConnected;
protected static string|BackedEnum|null $icon = TablerIcon::Network;
public function setTitle(): string
{
@@ -46,28 +49,14 @@ class AllocationsRelationManager extends RelationManager
->recordTitleAttribute('address')
->checkIfRecordIsSelectableUsing(fn (Allocation $allocation) => $allocation->server_id === null)
->paginationPageOptions([10, 20, 50, 100, 200, 500])
->searchable()
->heading('')
->heading(null)
->selectCurrentPageOnly() //Prevent people from trying to nuke 30,000 ports at once.... -,-
->columns([
TextColumn::make('id')
->label('ID')
->sortable()
->toggleable()
->toggledHiddenByDefault(),
TextColumn::make('port')
->searchable()
->label(trans('admin/node.ports')),
TextColumn::make('server.name')
->label(trans('admin/node.table.servers'))
->icon(TablerIcon::BrandDocker)
->visibleFrom('md')
->searchable()
->url(fn (Allocation $allocation): string => $allocation->server ? route('filament.admin.resources.servers.edit', ['record' => $allocation->server]) : ''),
TextInputColumn::make('ip_alias')
->searchable()
->label(trans('admin/node.table.alias')),
TextInputColumn::make('notes')
->label(trans('admin/node.table.allocation_notes'))
->placeholder(trans('admin/node.table.no_notes')),
SelectColumn::make('ip')
->options(function (Allocation $allocation) {
$ips = Allocation::where('port', $allocation->port)->pluck('ip');
@@ -81,15 +70,35 @@ class AllocationsRelationManager extends RelationManager
})
->selectablePlaceholder(false)
->searchable()
->sortable()
->label(trans('admin/node.table.ip')),
TextColumn::make('port')
->searchable()
->sortable()
->label(trans('admin/node.port')),
TextInputColumn::make('ip_alias')
->searchable()
->sortable()
->label(trans('admin/node.table.alias'))
->placeholder(trans('admin/node.table.no_alias')),
TextInputColumn::make('notes')
->label(trans('admin/node.table.allocation_notes'))
->placeholder(trans('admin/node.table.no_notes')),
TextColumn::make('server.name')
->label(trans('admin/node.table.servers'))
->placeholder(trans('admin/node.table.no_server'))
->visibleFrom('md')
->searchable()
->url(fn (Allocation $allocation) => $allocation->server && user()?->can('update', $allocation->server) ? EditServer::getUrl(['record' => $allocation->server]) : null),
])
->emptyStateHeading(trans('admin/node.no_allocations'))
->recordActions([
DeleteAction::make()
->visible(fn (Allocation $allocation) => $allocation->server_id === null),
])
->toolbarActions([
DeleteBulkAction::make()
->authorize(fn () => user()?->can('update', $this->getOwnerRecord())),
Action::make('create new allocation')
->label(trans('admin/node.create_allocation'))
->tooltip(trans('admin/node.create_allocation'))
CreateAction::make()
->createAnother(false)
->icon(TablerIcon::WorldPlus)
->schema(fn () => [
Select::make('allocation_ip')
@@ -144,6 +153,7 @@ class AllocationsRelationManager extends RelationManager
UpdateNodeAllocations::make()
->nodeRecord($this->getOwnerRecord())
->authorize(fn () => user()?->can('update', $this->getOwnerRecord())),
DeleteBulkAction::make(),
]);
}
}

View File

@@ -4,8 +4,13 @@ namespace App\Filament\Admin\Resources\Nodes\RelationManagers;
use App\Enums\ServerResourceType;
use App\Enums\TablerIcon;
use App\Filament\Admin\Resources\Eggs\Pages\EditEgg;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Admin\Resources\Users\Pages\EditUser;
use App\Filament\Components\Actions\ViewConsoleAction;
use App\Models\Server;
use BackedEnum;
use Filament\Actions\EditAction;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\Columns\TextColumn;
@@ -25,29 +30,27 @@ class ServersRelationManager extends RelationManager
public function table(Table $table): Table
{
return $table
->searchable(false)
->heading('')
->heading(null)
->columns([
TextColumn::make('user.username')
->label(trans('admin/node.table.owner'))
->url(fn (Server $server): string => route('filament.admin.resources.users.edit', ['record' => $server->user]))
->url(fn (Server $server) => user()?->can('update', $server->user) ? EditUser::getUrl(['record' => $server->user]) : null)
->searchable(),
TextColumn::make('name')
->label(trans('admin/node.table.name'))
->url(fn (Server $server): string => route('filament.admin.resources.servers.edit', ['record' => $server]))
->url(fn (Server $server) => user()?->can('update', $server) ? EditServer::getUrl(['record' => $server]) : null)
->searchable()
->sortable(),
TextColumn::make('egg.name')
->label(trans('admin/node.table.egg'))
->url(fn (Server $server): string => route('filament.admin.resources.eggs.edit', ['record' => $server->user]))
->url(fn (Server $server) => user()?->can('update', $server->egg) ? EditEgg::getUrl(['record' => $server->egg]) : null)
->sortable(),
SelectColumn::make('allocation.id')
->label(trans('admin/node.primary_allocation'))
->disabled(fn (Server $server) => $server->allocations->count() <= 1)
->options(fn (Server $server) => $server->allocations->take(1)->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address]))
->selectablePlaceholder(fn (Server $server) => $server->allocations->count() <= 1)
->placeholder(trans('admin/server.none'))
->sortable(),
->placeholder(trans('admin/server.none')),
TextColumn::make('cpu')
->label(trans('admin/node.cpu'))
->state(fn (Server $server) => $server->formatResource(ServerResourceType::CPULimit)),
@@ -61,13 +64,22 @@ class ServersRelationManager extends RelationManager
->counts('databases')
->label(trans('admin/node.databases'))
->numeric()
->sortable(),
->sortable()
->toggleable()
->toggledHiddenByDefault(),
TextColumn::make('backups_count')
->counts('backups')
->label(trans('admin/node.backups'))
->numeric()
->sortable(),
->sortable()
->toggleable()
->toggledHiddenByDefault(),
])
->emptyStateHeading(trans('admin/server.no_servers'));
->emptyStateHeading(trans('admin/server.no_servers'))
->recordActions([
ViewConsoleAction::make(),
EditAction::make()
->url(fn (Server $server) => EditServer::getUrl(['record' => $server], panel: 'admin')),
]);
}
}

View File

@@ -113,6 +113,7 @@ class PluginResource extends Resource
->color('primary')
->visible(fn (Plugin $plugin) => $plugin->status === PluginStatus::Enabled && $plugin->hasSettings())
->schema(fn (Plugin $plugin) => $plugin->getSettingsForm())
->fillForm(fn (Plugin $plugin) => $plugin->getSettingsFormData())
->action(fn (array $data, Plugin $plugin) => $plugin->saveSettings($data))
->slideOver(),
ActionGroup::make([

View File

@@ -67,7 +67,7 @@ class RoleResource extends Resource
public static function getNavigationGroup(): ?string
{
return user()?->getCustomization(CustomizationKey::TopNavigation) ? trans('admin/dashboard.advanced') : trans('admin/dashboard.user');
return user()?->getCustomization(CustomizationKey::TopNavigation) === 'topbar' ? trans('admin/dashboard.advanced') : trans('admin/dashboard.user');
}
public static function getNavigationBadge(): ?string

View File

@@ -3,12 +3,14 @@
namespace App\Filament\Admin\Resources\Servers\Pages;
use App\Enums\TablerIcon;
use App\Filament\Admin\Resources\Eggs\Pages\EditEgg;
use App\Filament\Admin\Resources\Nodes\Pages\EditNode;
use App\Filament\Admin\Resources\Servers\ServerResource;
use App\Filament\Server\Pages\Console;
use App\Filament\Admin\Resources\Users\Pages\EditUser;
use App\Filament\Components\Actions\ViewConsoleAction;
use App\Models\Server;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
use Filament\Actions\CreateAction;
use Filament\Actions\EditAction;
use Filament\Resources\Pages\ListRecords;
@@ -28,12 +30,11 @@ class ListServers extends ListRecords
public function table(Table $table): Table
{
return $table
->searchable(false)
->defaultGroup('node.name')
->groups([
Group::make('node.name')->getDescriptionFromRecordUsing(fn (Server $server): string => str($server->node->description)->limit(150)),
Group::make('user.username')->getDescriptionFromRecordUsing(fn (Server $server): string => $server->user->email),
Group::make('egg.name')->getDescriptionFromRecordUsing(fn (Server $server): string => str($server->egg->description)->limit(150)),
Group::make('node.name')->getDescriptionFromRecordUsing(fn (Server $server) => str($server->node->description)->limit(150)),
Group::make('user.username')->getDescriptionFromRecordUsing(fn (Server $server) => $server->user->email),
Group::make('egg.name')->getDescriptionFromRecordUsing(fn (Server $server) => str($server->egg->description)->limit(150)),
])
->columns([
TextColumn::make('condition')
@@ -54,19 +55,19 @@ class ListServers extends ListRecords
->sortable(),
TextColumn::make('node.name')
->label(trans('admin/server.node'))
->url(fn (Server $server) => route('filament.admin.resources.nodes.edit', ['record' => $server->node]))
->url(fn (Server $server) => user()?->can('update', $server->node) ? EditNode::getUrl(['record' => $server->node]) : null)
->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'node.name')
->sortable()
->searchable(),
TextColumn::make('egg.name')
->label(trans('admin/server.egg'))
->url(fn (Server $server) => route('filament.admin.resources.eggs.edit', ['record' => $server->egg]))
->url(fn (Server $server) => user()?->can('update', $server->egg) ? EditEgg::getUrl(['record' => $server->egg]) : null)
->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'egg.name')
->sortable()
->searchable(),
TextColumn::make('user.username')
->label(trans('admin/user.username'))
->url(fn (Server $server) => route('filament.admin.resources.users.edit', ['record' => $server->user]))
->url(fn (Server $server) => user()?->can('update', $server->user) ? EditUser::getUrl(['record' => $server->user]) : null)
->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'user.username')
->sortable()
->searchable(),
@@ -82,19 +83,23 @@ class ListServers extends ListRecords
->label(trans('admin/server.primary_allocation'))
->hidden(fn () => user()?->can('update server')) // TODO: update to policy check (fn (Server $server) --> $server is empty)
->state(fn (Server $server) => $server->allocation->address ?? trans('admin/server.none')),
TextColumn::make('image')->hidden(),
TextColumn::make('databases_count')
->counts('databases')
->label(trans('admin/server.databases'))
->numeric()
->sortable()
->toggleable()
->toggledHiddenByDefault(),
TextColumn::make('backups_count')
->counts('backups')
->label(trans('admin/server.backups'))
->numeric()
->sortable(),
->sortable()
->toggleable()
->toggledHiddenByDefault(),
])
->recordActions([
Action::make('view')
->tooltip(trans('admin/server.view'))
->icon(TablerIcon::Terminal)
->url(fn (Server $server) => Console::getUrl(panel: 'server', tenant: $server))
->authorize(fn (Server $server) => user()?->canAccessTenant($server)),
ViewConsoleAction::make(),
EditAction::make(),
])
->toolbarActions([

View File

@@ -7,6 +7,7 @@ use App\Filament\Admin\Resources\Servers\Pages\CreateServer;
use App\Models\Allocation;
use App\Models\Server;
use App\Services\Allocations\AssignmentService;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Actions\AssociateAction;
use Filament\Actions\CreateAction;
@@ -19,7 +20,6 @@ use Filament\Forms\Components\TextInput;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\TextInputColumn;
@@ -32,21 +32,30 @@ class AllocationsRelationManager extends RelationManager
{
protected static string $relationship = 'allocations';
protected static string|BackedEnum|null $icon = TablerIcon::Network;
public function table(Table $table): Table
{
return $table
->heading('')
->heading(null)
->selectCurrentPageOnly()
->recordTitleAttribute('address')
->recordTitle(fn (Allocation $allocation) => $allocation->address)
->inverseRelationship('server')
->columns([
TextColumn::make('ip')
->label(trans('admin/server.ip_address')),
->label(trans('admin/server.ip_address'))
->searchable()
->sortable(),
TextColumn::make('port')
->label(trans('admin/server.port')),
->label(trans('admin/server.port'))
->searchable()
->sortable(),
TextInputColumn::make('ip_alias')
->label(trans('admin/server.alias')),
->label(trans('admin/server.alias'))
->placeholder(trans('admin/server.no_alias'))
->searchable()
->sortable(),
TextInputColumn::make('notes')
->label(trans('admin/server.notes'))
->placeholder(trans('admin/server.no_notes')),
@@ -72,18 +81,26 @@ class AllocationsRelationManager extends RelationManager
->emptyStateHeading(trans('admin/server.no_allocations'))
->recordActions([
Action::make('make-primary')
->label(trans('admin/server.make_primary'))
->authorize(fn (Allocation $allocation) => user()?->can('update', $allocation))
->tooltip(trans('admin/server.make_primary'))
->icon(TablerIcon::Star)
->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords())
->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id),
Action::make('lock')
->label(trans('admin/server.lock'))
->authorize(fn (Allocation $allocation) => user()?->can('update', $allocation))
->tooltip(trans('admin/server.lock'))
->icon(TablerIcon::Lock)
->action(fn (Allocation $allocation) => $allocation->update(['is_locked' => true]) && $this->deselectAllTableRecords())
->hidden(fn (Allocation $allocation) => $allocation->is_locked),
Action::make('unlock')
->label(trans('admin/server.unlock'))
->authorize(fn (Allocation $allocation) => user()?->can('update', $allocation))
->tooltip(trans('admin/server.unlock'))
->icon(TablerIcon::LockOpen)
->action(fn (Allocation $allocation) => $allocation->update(['is_locked' => false]) && $this->deselectAllTableRecords())
->visible(fn (Allocation $allocation) => $allocation->is_locked),
DissociateAction::make()
->authorize(fn (Allocation $allocation) => user()?->can('update', $allocation))
->tooltip(trans('admin/server.remove_allocation'))
->after(function (Allocation $allocation) {
$allocation->update([
'notes' => null,
@@ -110,7 +127,7 @@ class AllocationsRelationManager extends RelationManager
CreateAction::make()
->hiddenLabel()
->tooltip(trans('admin/server.create_allocation'))
->icon(TablerIcon::Network)
->icon(TablerIcon::WorldPlus)
->createAnother(false)
->schema(fn () => [
Select::make('allocation_ip')
@@ -163,8 +180,6 @@ class AllocationsRelationManager extends RelationManager
])
->action(fn (array $data, AssignmentService $service) => $service->handle($this->getOwnerRecord()->node, $data, $this->getOwnerRecord())),
AssociateAction::make()
->icon(TablerIcon::FilePlus)
->iconButton()->iconSize(IconSize::ExtraLarge)
->multiple()
->associateAnother(false)
->preloadRecordSelect()

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Admin\Resources\Servers\RelationManagers;
use App\Enums\TablerIcon;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Components\Actions\RotateDatabasePasswordAction;
use App\Filament\Components\Tables\Columns\DateTimeColumn;
use App\Models\Database;
@@ -10,6 +11,7 @@ use App\Models\DatabaseHost;
use App\Models\Server;
use App\Services\Databases\DatabaseManagementService;
use App\Services\Servers\RandomWordService;
use BackedEnum;
use Exception;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
@@ -30,6 +32,8 @@ class DatabasesRelationManager extends RelationManager
{
protected static string $relationship = 'databases';
protected static string|BackedEnum|null $icon = TablerIcon::Database;
public function form(Schema $schema): Schema
{
return $schema
@@ -62,7 +66,7 @@ class DatabasesRelationManager extends RelationManager
public function table(Table $table): Table
{
return $table
->heading('')
->heading(null)
->recordTitleAttribute('database')
->columns([
TextColumn::make('database'),
@@ -72,7 +76,7 @@ class DatabasesRelationManager extends RelationManager
->label(trans('admin/databasehost.table.remote'))
->formatStateUsing(fn (Database $record) => $record->remote === '%' ? trans('admin/databasehost.anywhere'). ' ( % )' : $record->remote),
TextColumn::make('server.name')
->url(fn (Database $database) => route('filament.admin.resources.servers.edit', ['record' => $database->server_id])),
->url(fn (Database $database) => user()?->can('update', $database->server) ? EditServer::getUrl(['record' => $database->server]) : null),
TextColumn::make('max_connections')
->label(trans('admin/databasehost.table.max_connections'))
->formatStateUsing(fn ($record) => $record->max_connections ?: trans('admin/databasehost.unlimited')),

View File

@@ -50,7 +50,7 @@ class ServerResource extends Resource
public static function getNavigationGroup(): ?string
{
if (user()?->getCustomization(CustomizationKey::TopNavigation)) {
if (user()?->getCustomization(CustomizationKey::TopNavigation) === 'topbar') {
return null;
}

View File

@@ -4,10 +4,15 @@ namespace App\Filament\Admin\Resources\Users\RelationManagers;
use App\Enums\ServerState;
use App\Enums\SuspendAction;
use App\Filament\Admin\Resources\Eggs\Pages\EditEgg;
use App\Filament\Admin\Resources\Nodes\Pages\EditNode;
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
use App\Filament\Components\Actions\ViewConsoleAction;
use App\Models\Server;
use App\Models\User;
use App\Services\Servers\SuspensionService;
use Filament\Actions\Action;
use Filament\Actions\EditAction;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\Columns\TextColumn;
@@ -23,7 +28,6 @@ class ServersRelationManager extends RelationManager
$user = $this->getOwnerRecord();
return $table
->searchable(false)
->heading(trans('admin/user.servers'))
->headerActions([
Action::make('toggle_suspend')
@@ -50,22 +54,20 @@ class ServersRelationManager extends RelationManager
}),
])
->columns([
TextColumn::make('uuid')
->hidden()
->label('UUID')
->searchable(),
TextColumn::make('name')
->label(trans('admin/server.name'))
->url(fn (Server $server) => route('filament.admin.resources.servers.edit', ['record' => $server]))
->url(fn (Server $server) => user()?->can('update', $server) ? EditServer::getUrl(['record' => $server]) : null)
->searchable()
->sortable(),
TextColumn::make('node.name')
->label(trans('admin/server.node'))
->url(fn (Server $server) => route('filament.admin.resources.nodes.edit', ['record' => $server->node]))
->url(fn (Server $server) => user()?->can('update', $server->node) ? EditNode::getUrl(['record' => $server->node]) : null)
->searchable()
->sortable(),
TextColumn::make('egg.name')
->label(trans('admin/server.egg'))
->url(fn (Server $server) => route('filament.admin.resources.eggs.edit', ['record' => $server->egg]))
->url(fn (Server $server) => user()?->can('update', $server->egg) ? EditEgg::getUrl(['record' => $server->egg]) : null)
->searchable()
->sortable(),
SelectColumn::make('allocation_id')
->label(trans('admin/server.primary_allocation'))
@@ -83,13 +85,22 @@ class ServersRelationManager extends RelationManager
->counts('databases')
->label(trans('admin/server.databases'))
->numeric()
->sortable(),
->sortable()
->toggleable()
->toggledHiddenByDefault(),
TextColumn::make('backups_count')
->counts('backups')
->label(trans('admin/server.backups'))
->numeric()
->sortable(),
->sortable()
->toggleable()
->toggledHiddenByDefault(),
])
->emptyStateHeading(trans('admin/server.no_servers'));
->emptyStateHeading(trans('admin/server.no_servers'))
->recordActions([
ViewConsoleAction::make(),
EditAction::make()
->url(fn (Server $server) => EditServer::getUrl(['record' => $server], panel: 'admin')),
]);
}
}

View File

@@ -91,7 +91,7 @@ class UserResource extends Resource
public static function getNavigationGroup(): ?string
{
if (user()?->getCustomization(CustomizationKey::TopNavigation)) {
if (user()?->getCustomization(CustomizationKey::TopNavigation) === 'topbar') {
return null;
}
@@ -118,10 +118,12 @@ class UserResource extends Resource
->defaultImageUrl(fn (User $user) => Filament::getUserAvatarUrl($user)),
TextColumn::make('username')
->label(trans('admin/user.username'))
->searchable(),
->searchable()
->sortable(),
TextColumn::make('email')
->label(trans('admin/user.email'))
->searchable(),
->searchable()
->sortable(),
IconColumn::make('mfa_email_enabled')
->label(trans('profile.tabs.2fa'))
->visibleFrom('lg')

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Filament\Components\Actions;
use App\Enums\TablerIcon;
use App\Filament\Server\Pages\Console;
use App\Models\Server;
use Filament\Actions\Action;
use Filament\Facades\Filament;
class ViewConsoleAction extends Action
{
protected ?Server $server = null;
public static function getDefaultName(): ?string
{
return 'view_console';
}
protected function setUp(): void
{
parent::setUp();
$this->tooltip(trans('admin/server.view_console'));
$this->icon(TablerIcon::Terminal);
$this->url(fn (?Server $server) => Console::getUrl(panel: 'server', tenant: $this->getServer() ?? $server));
$this->authorize(fn (?Server $server) => user()?->canAccessTenant($this->getServer() ?? $server));
}
public function server(?Server $server): static
{
$this->server = $server;
return $this;
}
public function getServer(): ?Server
{
/** @var ?Server $tenant */
$tenant = Filament::getTenant();
return $this->server ?? $tenant;
}
}

View File

@@ -64,9 +64,15 @@ class Console extends Page
public function boot(FeatureService $featureService): void
{
$this->featureService = $featureService;
/** @var Server $server */
$server = Filament::getTenant();
foreach ($featureService->getActiveSchemas($server->egg->features) as $feature) {
if (!$feature->authorize(user(), $server)) {
continue;
}
$this->cacheAction($feature->getAction());
}
}
@@ -82,6 +88,13 @@ class Console extends Page
return;
}
/** @var Server $server */
$server = Filament::getTenant();
if (!$feature->authorize(user(), $server)) {
return;
}
if ($this->getMountedAction()) {
$this->replaceMountedAction($feature->getId());
} else {

View File

@@ -2,7 +2,6 @@
namespace App\Filament\Server\Pages;
use App\Enums\ServerUserSettingKey;
use App\Enums\SubuserPermission;
use App\Enums\TablerIcon;
use App\Facades\Activity;
@@ -15,7 +14,6 @@ use Exception;
use Filament\Actions\Action;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Infolists\Components\TextEntry;
use Filament\Notifications\Notification;
use Filament\Schemas\Components\Fieldset;
@@ -256,44 +254,9 @@ class Settings extends ServerFormPage
TextEntry::make('files_info')
->label(trans('server/setting.reinstall.body2')),
]),
Section::make(trans('server/setting.notifications.title'))
->columnSpanFull()
->schema([
Toggle::make(ServerUserSettingKey::ManualBackupNotifications->value)
->label(trans('server/setting.notifications.backup_manual.label'))
->helperText(trans('server/setting.notifications.backup_manual.helper'))
->live()
->afterStateUpdated(fn ($state, Server $server) => $this->updateNotificationSetting(ServerUserSettingKey::ManualBackupNotifications, (bool) $state, $server)),
Toggle::make(ServerUserSettingKey::ScheduledBackupNotifications->value)
->label(trans('server/setting.notifications.backup_scheduled.label'))
->helperText(trans('server/setting.notifications.backup_scheduled.helper'))
->live()
->afterStateUpdated(fn ($state, Server $server) => $this->updateNotificationSetting(ServerUserSettingKey::ScheduledBackupNotifications, (bool) $state, $server)),
]),
]);
}
protected function fillForm(): void
{
$data = $this->getRecord()->attributesToArray();
foreach (ServerUserSettingKey::cases() as $key) {
$data[$key->value] = (bool) user()?->getServerSetting($this->getRecord(), $key);
}
$this->form->fill($data);
}
public function updateNotificationSetting(ServerUserSettingKey $key, bool $state, Server $server): void
{
user()?->updateServerSetting($server, $key, $state);
Notification::make()
->title(trans('server/setting.notifications.saved'))
->success()
->send();
}
public function updateName(string $name, Server $server): void
{
abort_unless(user()?->can(SubuserPermission::SettingsRename, $server), 403);

View File

@@ -2,16 +2,9 @@
namespace App\Filament\Server\Resources\Backups\Pages;
use App\Enums\ServerUserSettingKey;
use App\Enums\TablerIcon;
use App\Filament\Server\Resources\Backups\BackupResource;
use App\Models\Server;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
class ListBackups extends ListRecords
@@ -21,39 +14,6 @@ class ListBackups extends ListRecords
protected static string $resource = BackupResource::class;
/** @return Action[] */
protected function getDefaultHeaderActions(): array
{
/** @var Server $server */
$server = Filament::getTenant();
return [
Action::make('notification_settings')
->label(trans('server/backup.notifications.action'))
->icon(TablerIcon::Bell)
->schema([
Toggle::make(ServerUserSettingKey::ManualBackupNotifications->value)
->label(trans('server/backup.notifications.toggle_manual'))
->helperText(trans('server/backup.notifications.helper_manual'))
->default(fn () => (bool) user()?->getServerSetting($server, ServerUserSettingKey::ManualBackupNotifications)),
Toggle::make(ServerUserSettingKey::ScheduledBackupNotifications->value)
->label(trans('server/backup.notifications.toggle_scheduled'))
->helperText(trans('server/backup.notifications.helper_scheduled'))
->default(fn () => (bool) user()?->getServerSetting($server, ServerUserSettingKey::ScheduledBackupNotifications)),
])
->action(function (array $data) use ($server) {
foreach (ServerUserSettingKey::cases() as $key) {
user()?->updateServerSetting($server, $key, (bool) $data[$key->value]);
}
Notification::make()
->title(trans('server/backup.notifications.saved'))
->success()
->send();
}),
];
}
public function getBreadcrumbs(): array
{
return [];

View File

@@ -2,11 +2,8 @@
namespace App\Listeners\Server;
use App\Enums\ServerUserSettingKey;
use App\Events\Server\BackupCompleted;
use App\Filament\Server\Resources\Backups\Pages\ListBackups;
use App\Models\ServerUserSettings;
use App\Models\User;
use App\Notifications\BackupCompleted as BackupCompletedNotification;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
@@ -15,47 +12,26 @@ class BackupCompletedListener
{
public function handle(BackupCompleted $event): void
{
$event->backup->loadMissing(['server.user', 'server.subusers.user']);
$event->backup->loadMissing('server');
$event->backup->server->loadMissing('user');
$server = $event->backup->server;
$locale = $event->backup->server->user->language ?? 'en';
$candidates = collect([$server->user])
->concat($server->subusers->map->user)
->filter()
->unique('id');
Notification::make()
->status($event->backup->is_successful ? 'success' : 'danger')
->title(trans('notifications.backup_' . ($event->backup->is_successful ? 'completed' : 'failed'), locale: $locale))
->body(trans('notifications.backup_body', ['name' => $event->backup->name, 'server' => $event->backup->server->name], $locale))
->actions([
Action::make('exclude_view')
->button()
->label(trans('notifications.view_backups', locale: $locale))
->markAsRead()
->url(fn () => ListBackups::getUrl(panel: 'server', tenant: $event->backup->server)),
])
->sendToDatabase($event->backup->server->user);
$settings = ServerUserSettings::query()
->where('server_id', $server->id)
->whereIn('user_id', $candidates->pluck('id'))
->get()
->keyBy('user_id');
// Users only receive notifications if they opted in for this kind of backup.
$key = $event->backup->is_scheduled ? ServerUserSettingKey::ScheduledBackupNotifications : ServerUserSettingKey::ManualBackupNotifications;
$recipients = $candidates->filter(function (User $user) use ($settings, $key) {
$userSettings = $settings->get($user->id)->settings ?? [];
return (bool) ($userSettings[$key->value] ?? $key->getDefaultValue());
});
foreach ($recipients as $user) {
$locale = $user->language ?? 'en';
Notification::make()
->status($event->backup->is_successful ? 'success' : 'danger')
->title(trans('notifications.backup_' . ($event->backup->is_successful ? 'completed' : 'failed'), locale: $locale))
->body(trans('notifications.backup_body', ['name' => $event->backup->name, 'server' => $server->name], $locale))
->actions([
Action::make('exclude_view')
->button()
->label(trans('notifications.view_backups', locale: $locale))
->markAsRead()
->url(fn () => ListBackups::getUrl(panel: 'server', tenant: $server)),
])
->sendToDatabase($user);
$user->notify(new BackupCompletedNotification($event->backup));
if (config()->get('panel.email.send_backup_completed_notification', true)) {
$event->backup->server->user->notify(new BackupCompletedNotification($event->backup));
}
}
}

View File

@@ -31,7 +31,6 @@ use Illuminate\Database\Query\Builder;
* @property bool $is_successful
* @property string|null $upload_id
* @property bool $is_locked
* @property bool $is_scheduled
* @property-read Server $server
* @property-read BackupStatus $status
*
@@ -70,7 +69,6 @@ class Backup extends Model implements Validatable
protected $attributes = [
'is_successful' => false,
'is_locked' => false,
'is_scheduled' => false,
'checksum' => null,
'bytes' => 0,
'upload_id' => null,
@@ -84,7 +82,6 @@ class Backup extends Model implements Validatable
'uuid' => ['required', 'uuid'],
'is_successful' => ['boolean'],
'is_locked' => ['boolean'],
'is_scheduled' => ['boolean'],
'name' => ['required', 'string'],
'ignored_files' => ['array'],
'backup_host_id' => ['required', 'integer', 'exists:backup_hosts,id'],
@@ -99,7 +96,6 @@ class Backup extends Model implements Validatable
'id' => 'int',
'is_successful' => 'bool',
'is_locked' => 'bool',
'is_scheduled' => 'bool',
'ignored_files' => 'array',
'bytes' => 'int',
'completed_at' => 'immutable_datetime',

View File

@@ -335,6 +335,21 @@ class Plugin extends Model implements HasPluginSettings
return false;
}
/** @return array<string, mixed> */
public function getSettingsFormData(): array
{
try {
$pluginObject = new ($this->fullClass());
if ($pluginObject instanceof HasPluginSettings) {
return $pluginObject->getSettingsFormData();
}
} catch (Exception) {
}
return [];
}
/** @return Component[] */
public function getSettingsForm(): array
{

View File

@@ -90,8 +90,6 @@ use Psr\Http\Message\ResponseInterface;
* @property-read int|null $server_variables_count
* @property-read Collection<int, Subuser> $subusers
* @property-read int|null $subusers_count
* @property-read Collection<int, ServerUserSettings> $userSettings
* @property-read int|null $user_settings_count
* @property-read ServerTransfer|null $transfer
* @property-read User $user
* @property-read Collection<int, EggVariable> $variables
@@ -273,16 +271,6 @@ class Server extends Model implements HasAvatar, Validatable
return $this->hasMany(Subuser::class, 'server_id', 'id');
}
/**
* Gets the per-user settings associated with a server.
*
* @return HasMany<ServerUserSettings, $this>
*/
public function userSettings(): HasMany
{
return $this->hasMany(ServerUserSettings::class);
}
/**
* Gets the default allocation for a server.
*/

View File

@@ -1,84 +0,0 @@
<?php
namespace App\Models;
use App\Contracts\Validatable;
use App\Traits\HasValidation;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property int $user_id
* @property int $server_id
* @property array<string, string|int|bool>|null $settings
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Server $server
* @property-read User $user
*
* @method static \Database\Factories\ServerUserSettingsFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereServerId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereSettings($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ServerUserSettings whereUserId($value)
*/
class ServerUserSettings extends Model implements Validatable
{
use HasFactory;
use HasValidation;
/**
* The resource name for this model when it is transformed into an
* API representation using fractal.
*/
public const RESOURCE_NAME = 'server_user_settings';
protected $table = 'server_user_settings';
/**
* Fields that are not mass assignable.
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/** @var array<array-key, string[]> */
public static array $validationRules = [
'user_id' => ['required', 'numeric', 'exists:users,id'],
'server_id' => ['required', 'numeric', 'exists:servers,id'],
'settings' => ['nullable', 'array'],
'settings.manual_backup_notifications' => ['boolean'],
'settings.scheduled_backup_notifications' => ['boolean'],
];
protected function casts(): array
{
return [
'user_id' => 'int',
'server_id' => 'int',
'settings' => 'array',
];
}
/**
* Gets the server these settings are associated with.
*/
public function server(): BelongsTo
{
return $this->belongsTo(Server::class);
}
/**
* Gets the user these settings are associated with.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@@ -4,7 +4,6 @@ namespace App\Models;
use App\Contracts\Validatable;
use App\Enums\CustomizationKey;
use App\Enums\ServerUserSettingKey;
use App\Enums\SubuserPermission;
use App\Events\User\Deleting;
use App\Exceptions\DisplayException;
@@ -87,8 +86,6 @@ use Spatie\Permission\Traits\HasRoles;
* @property-read int|null $sub_servers_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, Subuser> $subusers
* @property-read int|null $subusers_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, ServerUserSettings> $serverSettings
* @property-read int|null $server_settings_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, ApiKey> $tokens
* @property-read int|null $tokens_count
*
@@ -354,30 +351,6 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
return $this->belongsToMany(Server::class, 'subusers');
}
/** @return HasMany<ServerUserSettings, $this> */
public function serverSettings(): HasMany
{
return $this->hasMany(ServerUserSettings::class);
}
public function getServerSetting(Server $server, ServerUserSettingKey $key): string|int|bool
{
$settings = $this->serverSettings()->where('server_id', $server->id)->first()->settings ?? [];
return $settings[$key->value] ?? $key->getDefaultValue();
}
public function updateServerSetting(Server $server, ServerUserSettingKey $key, string|int|bool $value): void
{
$row = $this->serverSettings()->firstOrNew(['server_id' => $server->id]);
$settings = $row->settings ?? [];
$settings[$key->value] = $value;
$row->settings = array_intersect_key($settings, ServerUserSettingKey::getDefaultSettings());
$row->save();
}
/** @return ($key is null ? array<string, string|int|bool> : string|int|bool) */
public function getCustomization(?CustomizationKey $key = null): array|string|int|bool|null
{

View File

@@ -6,8 +6,10 @@ use App\Enums\CustomizationKey;
use App\Enums\TablerIcon;
use App\Livewire\Passkeys;
use Filament\Actions\Action;
use Filament\Actions\AssociateAction;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\DissociateAction;
use Filament\Actions\EditAction;
use Filament\Actions\View\ActionsIconAlias;
use Filament\Actions\ViewAction;
@@ -27,6 +29,7 @@ use Filament\Support\Facades\FilamentColor;
use Filament\Support\Facades\FilamentIcon;
use Filament\Support\Facades\FilamentView;
use Filament\Support\View\SupportIconAlias;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\View\TablesIconAlias;
use Filament\View\PanelsIconAlias;
use Filament\View\PanelsRenderHook;
@@ -104,6 +107,8 @@ class FilamentServiceProvider extends ServiceProvider
Select::configureUsing(fn (Select $select) => $select->native(false));
SelectColumn::configureUsing(fn (SelectColumn $select) => $select->native(false));
KeyValue::configureUsing(fn (KeyValue $keyValue) => $keyValue
->addAction(function (Action $action) {
$action->tooltip(fn () => $action->getLabel());
@@ -197,6 +202,30 @@ class FilamentServiceProvider extends ServiceProvider
}
});
AssociateAction::configureUsing(function (AssociateAction $action) {
$action->icon(TablerIcon::Link);
$action->tooltip(fn () => $action->getLabel());
$action->hiddenLabel();
$action->iconSize(IconSize::Large);
if (user()?->getCustomization(CustomizationKey::ButtonStyle)) {
$action->iconButton();
$action->iconSize(IconSize::ExtraLarge);
}
});
DissociateAction::configureUsing(function (DissociateAction $action) {
$action->icon(TablerIcon::Unlink);
$action->tooltip(fn () => $action->getLabel());
$action->hiddenLabel();
$action->iconSize(IconSize::Large);
if (user()?->getCustomization(CustomizationKey::ButtonStyle)) {
$action->iconButton();
$action->iconSize(IconSize::ExtraLarge);
}
});
Action::configureUsing(function (Action $action) {
$action->iconSize(IconSize::Large);

View File

@@ -35,7 +35,11 @@ class DeleteBackupService
}
$this->connection->transaction(function () use ($schema, $backup) {
$schema->deleteBackup($backup);
try {
$schema->deleteBackup($backup);
} catch (Exception $exception) {
throw_if($backup->is_successful, $exception);
}
$backup->delete();
});

View File

@@ -21,8 +21,6 @@ class InitiateBackupService
private bool $isLocked = false;
private bool $isScheduled = false;
/**
* InitiateBackupService constructor.
*/
@@ -43,16 +41,6 @@ class InitiateBackupService
return $this;
}
/**
* Set if the backup was initiated by a schedule rather than a user.
*/
public function setIsScheduled(bool $isScheduled): self
{
$this->isScheduled = $isScheduled;
return $this;
}
/**
* Sets the files to be ignored by this backup.
*
@@ -137,7 +125,6 @@ class InitiateBackupService
'ignored_files' => array_values($this->ignoredFiles ?? []),
'backup_host_id' => $backupHost->id,
'is_locked' => $this->isLocked,
'is_scheduled' => $this->isScheduled,
]);
$schema->createBackup($backup);

View File

@@ -20,7 +20,6 @@ class BackupTransformer extends BaseClientTransformer
'uuid' => $backup->uuid,
'is_successful' => $backup->is_successful,
'is_locked' => $backup->is_locked,
'is_scheduled' => $backup->is_scheduled,
'name' => $backup->name,
'ignored_files' => $backup->ignored_files,
'checksum' => $backup->checksum,

View File

@@ -16,7 +16,7 @@
"filament/filament": "^5.6",
"gboquizosanchez/filament-log-viewer": "^2.3",
"guzzlehttp/guzzle": "^7.13",
"laravel/framework": "^13.19",
"laravel/framework": "^13.21",
"laravel/helpers": "^1.8",
"laravel/passkeys": "^0.2",
"laravel/sanctum": "^4.3",

395
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -101,7 +101,7 @@ return [
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'search_path' => env('DB_SCHEMA', 'public'),
'sslmode' => 'prefer',
],

View File

@@ -55,6 +55,8 @@ return [
'send_install_notification' => env('PANEL_SEND_INSTALL_NOTIFICATION', true),
// Should an email be sent to a server owner whenever their server is reinstalled?
'send_reinstall_notification' => env('PANEL_SEND_REINSTALL_NOTIFICATION', true),
// Should an email be sent to a server owner whenever a backup is completed?
'send_backup_completed_notification' => env('PANEL_SEND_BACKUP_COMPLETED_NOTIFICATION', true),
],
'filament' => [

View File

@@ -23,7 +23,10 @@ class AllocationFactory extends Factory
{
return [
'ip' => $this->faker->unique()->ipv4(),
'port' => $this->faker->unique()->numberBetween(1024, 65535),
// stay above the ports some tests hardcode (e.g. 5000-5005) on the
// same node and ip, otherwise the unique (node_id, ip, port) index
// makes those tests randomly fail
'port' => $this->faker->unique()->numberBetween(10000, 65535),
'node_id' => Node::factory(),
];
}

View File

@@ -1,56 +0,0 @@
<?php
namespace Database\Factories;
use App\Enums\ServerUserSettingKey;
use App\Models\ServerUserSettings;
use Illuminate\Database\Eloquent\Factories\Factory;
class ServerUserSettingsFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ServerUserSettings::class;
/**
* Define the model's default state.
*/
public function definition(): array
{
return [
'settings' => [
ServerUserSettingKey::ManualBackupNotifications->value => true,
ServerUserSettingKey::ScheduledBackupNotifications->value => true,
],
];
}
/**
* Indicate the user has opted in to all backup notifications.
*/
public function optedIn(): static
{
return $this->state([
'settings' => [
ServerUserSettingKey::ManualBackupNotifications->value => true,
ServerUserSettingKey::ScheduledBackupNotifications->value => true,
],
]);
}
/**
* Indicate the user has opted out of all backup notifications.
*/
public function optedOut(): static
{
return $this->state([
'settings' => [
ServerUserSettingKey::ManualBackupNotifications->value => false,
ServerUserSettingKey::ScheduledBackupNotifications->value => false,
],
]);
}
}

View File

@@ -34,10 +34,7 @@ return new class extends Migration
});
Schema::table('backups', function (Blueprint $table) {
$table->unsignedInteger('backup_host_id')->after('disk');
$table->foreign('backup_host_id')->references('id')->on('backup_hosts');
$table->dropColumn('disk');
$table->unsignedInteger('backup_host_id')->nullable()->after('disk');
});
$oldDriver = env('APP_BACKUP_DRIVER', 'wings');
@@ -64,6 +61,14 @@ return new class extends Migration
]);
DB::table('backups')->update(['backup_host_id' => $backupHost->id]);
Schema::table('backups', function (Blueprint $table) {
$table->unsignedInteger('backup_host_id')->nullable(false)->change();
$table->foreign('backup_host_id')->references('id')->on('backup_hosts');
$table->dropColumn('disk');
});
}
/**
@@ -78,8 +83,8 @@ return new class extends Migration
$table->dropColumn('backup_host_id');
});
Schema::dropIfExists('backup_hosts');
Schema::dropIfExists('backup_host_node');
Schema::dropIfExists('backup_hosts');
}
};

View File

@@ -1,48 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('server_user_settings', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id');
$table->unsignedInteger('server_id');
$table->json('settings')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
$table->foreign('server_id')->references('id')->on('servers')->cascadeOnDelete();
$table->unique(['user_id', 'server_id']);
});
// Backup notifications now default off for everyone. Owners on existing
// installs previously always received them, so seed an opt-in row for each
// server's owner unless the panel-wide email switch was already disabled.
if (!filter_var(env('PANEL_SEND_BACKUP_COMPLETED_NOTIFICATION', true), FILTER_VALIDATE_BOOL)) {
return;
}
$now = now();
DB::table('servers')->select(['id', 'owner_id'])->orderBy('id')->chunkById(250, function ($servers) use ($now) {
DB::table('server_user_settings')->insert($servers->map(fn ($server) => [
'user_id' => $server->owner_id,
'server_id' => $server->id,
'settings' => json_encode(['manual_backup_notifications' => true, 'scheduled_backup_notifications' => true]),
'created_at' => $now,
'updated_at' => $now,
])->all());
});
}
public function down(): void
{
Schema::dropIfExists('server_user_settings');
}
};

View File

@@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('backups', function (Blueprint $table) {
$table->boolean('is_scheduled')->default(false)->after('is_locked');
});
}
public function down(): void
{
Schema::table('backups', function (Blueprint $table) {
$table->dropColumn('is_scheduled');
});
}
};

View File

@@ -0,0 +1,14 @@
<?php
return [
'model_label' => 'Backupvært|Backupværter',
'name' => 'Navn',
'schema' => 'Skema',
'backups' => 'Sikkerhedskopier',
'linked_nodes' => 'Forbundne noder',
'all_nodes' => 'Alle noder',
'configuration' => 'Konfiguration',
'no_configuration' => 'Ingen yderligere konfiguration påkrævet',
'no_backup_hosts' => 'Ingen backupværter',
'local_backups_only' => 'Alle sikkerhedskopier vil blive oprettet lokalt på den respektive node',
];

View File

@@ -0,0 +1,45 @@
<?php
return [
'heading' => 'Velkommen til :app!',
'version' => 'Version: :version',
'advanced' => 'Avanceret',
'server' => 'Server',
'user' => 'Bruger',
'sections' => [
'intro-developers' => [
'heading' => 'Information til udviklere',
'content' => 'Tak for at prøve udviklingsversionen!',
'extra_note' => 'Hvis du løber ind i problemer, kan du rapportere dem på GitHub.',
'button_issues' => 'Opret Problem',
'button_features' => 'Diskutér Features',
],
'intro-update-available' => [
'heading' => 'Opdatering tilgængelig',
'content' => ':latestVersion er nu tilgængelig! Læs vores dokumentation for at opdatere dit panel.',
'button_changelog' => 'Hvad er nyt?',
],
'intro-no-update' => [
'heading' => 'Panelet er opdateret',
'content' => 'Du benytter i øjeblikket :version. Dit panel er opdateret!',
],
'intro-first-node' => [
'heading' => 'Ingen Nodes fundet',
'content' => 'Ser ikke ud til at der er nogen nodes opsat endnu, klik på handlingsknappen for at oprette den første!',
'extra_note' => 'Hvis du løber ind i nogen problemer, bedes du rapportere dem på GitHub.',
'button_label' => 'Opret første node',
],
'intro-support' => [
'heading' => 'Støt Pelican',
'content' => 'Tak fordi du bruger Pelican, det kunne kun lade sig gøre med støtte fra dig, vores bidragsydere og resten af vores støtter!',
'extra_note' => 'Vi sætter pris på enhver form for støtte fra alle.',
'button_translate' => 'Hjælp os med at oversætte',
'button_donate' => 'Doner Direkte',
],
'intro-help' => [
'heading' => 'Brug for hjælp?',
'content' => 'Tjek dokumentationen først! Hvis du stadig har brug for hjælp, så tilslut dig vores Discord server!',
'button_docs' => 'Læs dokumentation',
],
],
];

View File

@@ -35,7 +35,9 @@ return [
'linked_nodes_help' => 'Denne indstilling falder kun tilbage på denne databasevært, når der føjes en database til en server på den valgte node.',
'connection_error' => 'Fejl under tilslutning til databasevært',
'no_database_hosts' => 'Ingen databaseværter',
'no_databases' => 'Ingen databaser',
'no_nodes' => 'Ingen noder',
'nodes' => 'Noder',
'delete_help' => 'Databaseværten har stadig databaser',
'unlimited' => 'Ubegrænset',
'anywhere' => 'Hvor som helst',

126
lang/da/admin/egg.php Normal file
View File

@@ -0,0 +1,126 @@
<?php
return [
'nav_title' => 'Eggs',
'model_label' => 'Egg',
'model_label_plural' => 'Eggs',
'tabs' => [
'configuration' => 'Opsætning',
'process_management' => 'Proceshåndtering',
'egg_variables' => 'Egg-variabler',
'install_script' => 'Installations-script',
],
'import' => [
'file' => 'Fil',
'url' => 'URL',
'icon_url' => 'Ikon URL',
'icon_error' => 'Kunne ikke hente ikonet',
'egg_help' => 'Dette bør være den rå .json-fil ( egg-minecraft.json )',
'url_help' => 'URL\'er skal pege direkte på den rå .json-fil',
'add_url' => 'Ny URL',
'import_failed' => 'Import mislykkedes',
'import_success' => 'Import udført',
'import_result' => 'Importeret :success af :total egg',
'imported_eggs' => 'Importeret: :eggs',
'failed_import_eggs' => 'Fejlede: :eggs',
'github' => 'GitHub',
'refresh' => 'Opdater',
'import_icon' => 'Importér ikon',
'delete_icon' => 'Slet ikon',
'no_local_ip' => 'Lokale IP adresser er ikke tilladt',
'unsupported_format' => 'Ikke Understøttet Format. Understøttede Formater: Formater: Formater',
'invalid_url' => 'Det angivne URL er ugyldig',
'unknown_extension' => 'Ukendt ikon forlængelse (:extension)',
'could_not_write' => 'Kunne ikke gemme ikonet til disken',
'icon_deleted' => 'Ikon Slettet',
'no_icon' => 'Intet Ikon Valgt',
'icon_updated' => 'Ikon Opdateret',
],
'export' => [
'modal' => 'Hvordan vil du eksportere :egg ?',
'as' => 'Som .:format',
],
'in_use' => 'I brug',
'servers' => 'Servere',
'name' => 'Navn',
'egg_uuid' => 'Egg UUID',
'egg_id' => 'Egg ID',
'name_help' => 'Et simpelt, menneskeligt navn til brug som en identifikator for dette Egg.',
'author' => 'Forfatter',
'uuid_help' => 'Dette er den globale, unikke identifikation for dette Egg, som Wings bruger som en identifikator.',
'author_help' => 'Forfatteren til denne version af ægget.',
'author_help_edit' => 'Forfatteren til denne version af ægget. Upload en ny konfiguration fra en anden forfatter for at ændre dette.',
'description' => 'Beskriveslse',
'description_help' => 'En beskrivelse af dette æg vist i panelet efter behov.',
'add_startup' => 'Opstartskommando',
'startup_command' => 'Kommando',
'startup_commands' => 'Opstartskommando',
'startup_name' => 'Visningsnavn',
'startup_help' => 'De opstartskommandoer, der er tilgængelige for servere ved hjælp af dette egg. Den første er standard.',
'file_denylist' => 'Filsortlist',
'file_denylist_help' => 'En liste over filer, som slutbrugeren ikke må redigere.',
'features' => 'Features',
'force_ip' => 'Tving udgående IP',
'force_ip_help' => 'Tvinger al udgående netværkstrafik til at have sin Kilde-IP NAT\'et til serverens primære tildelte IP.
Kræves, for at visse spil fungerer korrekt, når noden har flere offentlige IP-adresser.
Aktivering af denne mulighed deaktiverer intern netværkstrafik for alle servere, som bruger dette Egg, hvilket betyder, at de ikke internt kan tilgå andre servere på samme node',
'tags' => 'Tags',
'update_url' => 'Opdatér URL',
'update_url_help' => 'URL\'er skal pege direkte på den rå .json-fil',
'add_image' => 'Tilføj Docker image',
'docker_images' => 'Docker Images',
'docker_name' => 'Image navn',
'docker_uri' => 'Image URI',
'docker_help' => 'De opstartskommandoer, der er tilgængelige for servere ved hjælp af dette egg. Den første er standard.',
'stop_command' => 'Stopkommando',
'stop_command_help' => 'Kommandoen, der skal sendes til serverprocesser for at stoppe dem yndefuldt. Ved behov for at sende en SIGINT, angiv ^C her.',
'copy_from' => 'Kopiér indstillinger fra',
'copy_from_help' => 'Ønskes tilbagefald til standardindstillingerne fra et andet Eeg, vælg det fra menuen ovenfor.',
'none' => 'Ingen',
'start_config' => 'Start opsætning',
'start_config_help' => 'Liste over værdier dæmonen skal lede efter ved opstart af en server for at bestemme færdiggørelsen.',
'config_files' => 'Konfigurationsfiler',
'config_files_help' => 'Dette bør være en JSON-repræsentation af opsætningsfiler til ændring, og hvilke dele, som skal ændres.',
'log_config' => 'Logkonfiguration',
'log_config_help' => 'Dette skal være en JSON-repræsentation af, hvor logfiler gemmes, og hvorvidt dæmonen skal oprette tilpassede logger.',
'environment_variable' => 'Miljøvariabel',
'default_value' => 'Standardværdi',
'user_permissions' => 'Brugertilladelser',
'viewable' => 'Synlig',
'editable' => 'Redigerbar',
'rules' => 'Regler',
'add_new_variable' => 'Tilføj ny variabel',
'error_unique' => 'En variabel med dette navn findes allerede.',
'error_required' => 'Miljøvariabel obligatorisk.',
'error_reserved' => 'Denne miljøvariabel er reserveret og kan ikke anvendes.',
'script_from' => 'Script fra',
'script_container' => 'Script-kontainer',
'script_entry' => 'Script-post',
'script_install' => 'Installations-script',
'no_eggs' => 'Ingen Eggs',
'no_servers' => 'Ingen Servere',
'no_servers_help' => 'Ingen servere tildelt dette Egg.',
'update' => 'Opdater|Opdater valgte',
'updated' => 'Egg opdateret|:count/:total Egg opdateret',
'updated_failed' => ':count mislykkedes',
'updated_skipped' => ':count sprunget over',
'update_success' => ':egg opdateret',
'update_failed' => 'Kunne ikke opdatere :egg',
'update_question' => 'Er du sikker på, at du vil opdatere dette egg?|Er du sikker på, at du vil opdatere de valgte æg?',
'update_description' => 'Hvis du har foretaget ændringer i ægget, vil de blive overskrevet!|Hvis du har foretaget ændringer i æggene, vil de blive overskrevet!',
'no_updates' => 'Ingen opdateringer til de valgte egg er tilgængelige',
'cannot_update' => 'Kan ikke opdatere :count egg(s)',
'no_update_url' => 'Følgende æg har ikke en fungerende opdaterings-URL angivet: :eggs',
'cannot_delete' => 'Kan ikke opdatere :count egg(s)',
'eggs_have_servers' => 'Følgende æg har servere tilknyttet og kan ikke slettes: :eggs',
'updated_from' => 'Opdateres succesfuldt fra: :url',
'update_error' => 'Fejl: :error',
'updated_eggs' => 'Opdateret: :eggs',
'failed_eggs' => 'Fejlede: :eggs',
'skipped_eggs' => 'Sprunget over: :eggs',
];

View File

@@ -0,0 +1,11 @@
<?php
return [
'title' => 'Aktivitet',
'event' => 'Begivenhed',
'user' => 'Bruger',
'deleted_user' => 'Slettet bruger',
'system' => 'System',
'timestamp' => 'Tidsstempel',
'metadata' => 'Metadata',
];

View File

@@ -35,7 +35,9 @@ return [
'linked_nodes_help' => 'Diese Einstellung bewirkt nur, dass standardmäßig auf dieser Datenbank Host genutzt wird, wenn eine Datenbank zu einem Server auf den ausgewählten Nodes hinzugefügt wird.',
'connection_error' => 'Fehler beim Verbinden mit dem Datenbank Host',
'no_database_hosts' => 'Keine Datenbank Hosts',
'no_databases' => 'Keine Datenbanken',
'no_nodes' => 'Keine Nodes',
'nodes' => 'Nodes',
'delete_help' => 'Datenbank Host hat Datenbanken',
'unlimited' => 'Unbegrenzt',
'anywhere' => 'Überall',

View File

@@ -20,6 +20,7 @@ return [
'disable' => 'Deaktivieren',
'import_from_file' => 'Von Datei importieren',
'import_from_url' => 'Von URL importieren',
'file' => 'Datei',
'no_plugins' => 'Keine Plugins',
'all' => 'Alle',
'change_load_order' => 'Ladereihenfolge ändern',
@@ -45,15 +46,25 @@ return [
],
'notifications' => [
'goto_plugins' => 'Gehe zu Plugins',
'background_info' => 'Dieser Prozess kann einige Sekunden dauern. Sie werden benachrichtigt, sobald er beendet ist.',
'install_started' => 'Plugin Installation im Hintergrund gestartet',
'installed' => 'Plugin installiert',
'install_error' => 'Plugin konnte nicht installiert werden',
'uninstall_started' => 'Plugin Deinstallation im Hintergrund gestartet',
'uninstalled' => 'Plugin deinstalliert',
'uninstall_error' => 'Plugin konnte nicht deinstalliert werden',
'deleted' => 'Plugin gelöscht',
'update_started' => 'Plugin Update im Hintergrund gestartet',
'updated' => 'Plugin aktualisiert',
'update_error' => 'Plugin konnte nicht aktualisiert werden',
'enabled' => 'Plugin aktiviert',
'disabled' => 'Plugin deaktiviert',
'deleted' => 'Plugin gelöscht',
'imported' => 'Plugin importiert',
'import_exists' => 'Ein Plugin mit dieser ID existiert bereits',
'import_failed' => 'Plugin konnte nicht aktualisiert werden',

View File

@@ -14,4 +14,36 @@ return [
'users' => 'Benutzer',
'nodes' => 'Nodes',
'nodes_hint' => 'Leer lassen für Zugriff auf alle Nodes',
// Permission section headings (RolePermissionModels enum + special permission groups)
'models' => [
'apiKey' => 'API Schlüssel',
'allocation' => 'Zuweisung',
'databaseHost' => 'Datenbank Host',
'database' => 'Datenbank',
'egg' => 'Egg',
'mount' => 'Einhängepunkt',
'node' => 'Node',
'role' => 'Rolle',
'server' => 'Server',
'user' => 'Nutzer',
'webhook' => 'Webhook',
'settings' => 'Einstellungen',
'health' => 'Gesundheit',
'activityLog' => 'Aktivitätslog',
'panelLog' => 'Panel Log',
'plugin' => 'Plugin',
],
// Permission checkbox labels (RolePermissionPrefixes enum + model-specific/special prefixes)
'permissions_list' => [
'viewList' => 'Zeige Liste',
'view' => 'Anzeigen',
'create' => 'Erstellen',
'update' => 'Aktualisieren',
'delete' => 'Löschen',
'import' => 'Importieren',
'export' => 'Exportieren',
'seeIps' => 'IP\'s anzeigen',
],
];

View File

@@ -6,17 +6,22 @@ return [
'model_label_plural' => 'Webhooks',
'endpoint' => 'Endpunkt',
'description' => 'Beschreibung',
'name' => 'Name',
'type' => 'Typ',
'server' => 'Server',
'information' => 'Information',
'payload' => 'Auslastung',
'events' => 'Ereignisse',
'no_webhooks' => 'Keine Webhooks',
'help' => 'Hilfe',
'help_text' => 'Du musst den Variablennamen zwischen {{ }} einschließen. Wenn Du z. B. den Namen aus der API abrufen möchten, kannst Du {{name}} verwenden.',
'test_now' => 'Jetzt Testen',
'test_now_help' => 'Dies löst das `created: Server` Event aus',
'test_now' => 'Jetzt testen',
'test_now_help' => 'Dadurch wird ein `created: Server`-Ereignis ausgelöst',
'table' => [
'description' => 'Beschreibung',
'endpoint' => 'Endpunkt',
],
'headers' => 'Kopfzeilen',
'events' => 'Ereignisse',
'regular' => 'Regelmäßig',
'reset_headers' => 'Kopfzeilen zurücksetzen',
'discord' => 'Discord',

View File

@@ -60,5 +60,11 @@ return [
],
'server' => [
'marked_as_failed' => 'Dieser Server hat seinen Installationsprozess noch nicht abgeschlossen, bitte versuche es später erneut.',
'file_too_large' => 'Die Datei, die du versuchst zu öffnen, ist zu groß, um es im Dateieditor anzuzeigen.',
'state_conflict' => 'Dieser Server ist im Moment in einem nicht unterstütztem Zustand, bitte versuchen Sie es später erneut.',
'suspended' => 'Dieser Server ist im Moment suspendiert und die erwünschte Funktionalität ist nicht verfügbar.',
'maintenance' => 'Der Node dieses Servers ist im Moment in Wartung und die erwünschte Funktionalität ist nicht verfügbar.',
'restoring_backup' => 'Dieser Server ist im Moment am Wiederherstellen von einem Backup, bitte versuchen Sie es später erneut.',
'transferring' => 'Dieser Server wird im Moment zu einer neuen Maschine bewegt, bitte versuchen Sie es später erneut.',
],
];

19
lang/de/passkeys.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
return [
'authenticate_using_passkey' => 'Mit Passkey authentifizieren',
'create' => 'Erstellen',
'delete' => 'Löschen',
'error_something_went_wrong_generating_the_passkey' => 'Etwas ist beim Generieren des Passkeys fehlgeschlagen',
'invalid' => 'Ungültiger Passkey',
'last_used' => 'Zuletzt genutzt',
'name' => 'Name',
'name_placeholder' => 'Mein Passkey',
'no_passkeys_registered' => 'Keine Passkeys registriert',
'not_used_yet' => 'Noch nicht benutzt',
'passkeys' => 'Passkeys',
'description' => 'Passkeys lassen Sie sich ohne Passwort anmelden. Statt einem Passwort können Sie ein Passkey generieren, der in 1Password, dem macOS Passwörter-Programm oder einem Alternativprogramm auf dem Betriebssystem deiner Wahl gespeichert wird.',
'created_notification_title' => 'Dein Passkey wurde erstellt',
'deleted_notification_title' => 'Dein Passkey wurde gelöscht',
'registration_failed_notification_title' => 'Passkey-Registrierung fehlgeschlagen',
];

View File

@@ -11,6 +11,7 @@ return [
'keys' => 'Schlüssel',
'2fa' => '2FA',
'customization' => 'Anpassung',
'passkeys' => 'Passkeys',
],
'username' => 'Benutzername',
'admin' => 'Administrator',
@@ -64,7 +65,13 @@ return [
'sidebar' => 'Seitenleiste',
'topbar' => 'Kopfzeile',
'mixed' => 'Gemischt',
'button_style' => 'Knopfstil',
'icon' => 'Icon',
'icon_button' => 'Icon Knopf',
'redirect_to_admin' => 'Zur Admin Oberfläche nach dem Login weiterleiten.',
'redirect_to_admin_help' => 'Wenn diese Option aktiviert ist, werden Sie nach der Anmeldung zum Admin-Bereich weitergeleitet, anstatt zur Serverliste.',
'no_oauth' => 'Keine Konten verknüpft',
'no_api_keys' => 'Keine API-Schlüssel',
'no_ssh_keys' => 'Keine SSH-Schlüssel',
'activity_info' => 'Zeige die letzten 50 Aktivitätsprotokolle',
];

View File

@@ -12,6 +12,7 @@ return [
'cron' => 'Cron',
'status' => 'Status',
'schedule_status' => [
'new' => 'Neu',
'inactive' => 'Inaktiv',
'processing' => 'Verarbeiten',
'active' => 'Aktiv',

View File

@@ -25,6 +25,8 @@ return [
'owner' => 'Owner',
'allocation_notes' => 'Notes',
'no_notes' => 'No notes',
'no_server' => 'No server',
'no_alias' => 'No alias',
],
'node_info' => 'Node Information',
'wings_version' => 'Wings Version',

View File

@@ -15,6 +15,7 @@ return [
'ports' => 'Ports',
'alias' => 'Alias',
'alias_helper' => 'Optional display name to help you remember what these are.',
'no_alias' => 'No Alias',
'locked' => 'Locked?',
'locked_helper' => 'Users won\'t be able to delete locked allocations',
'lock' => 'Lock',
@@ -110,7 +111,8 @@ return [
'keep_old_variables' => 'Keep old variables if possible?',
'create_allocation' => 'Create Allocation',
'add_allocation' => 'Add Allocation',
'view' => 'View',
'remove_allocation' => 'Remove Allocation',
'view_console' => 'View Console',
'no_log' => 'No Log Available',
'select_backups' => 'Select Backups',
'warning_backups' => 'Be aware, not transferred backups will be deleted.',

View File

@@ -121,6 +121,7 @@ return [
'removed_from_server' => 'Removed from Server',
'server_installed' => 'Server Installed',
'server_reinstalled' => 'Server Reinstalled',
'backup_completed' => 'Backup Completed',
],
'connections' => [
'title' => 'Connections',

View File

@@ -12,14 +12,6 @@ return [
'successful' => 'Successful',
'failed' => 'Failed',
],
'notifications' => [
'action' => 'Notification Settings',
'toggle_manual' => 'Manual Backup Notifications',
'helper_manual' => 'Receive a notification and email when a manually created backup for this server completes or fails.',
'toggle_scheduled' => 'Scheduled Backup Notifications',
'helper_scheduled' => 'Receive a notification and email when a scheduled backup for this server completes or fails.',
'saved' => 'Notification Settings Updated',
],
'actions' => [
'create' => [
'title' => 'Create Backup',

View File

@@ -41,18 +41,6 @@ return [
'password_body' => 'Your SFTP password is the same as the password you use to access this panel.',
],
],
'notifications' => [
'title' => 'Notifications',
'saved' => 'Notification Settings Updated',
'backup_manual' => [
'label' => 'Manual Backup Notifications',
'helper' => 'Receive a notification and email when a manually created backup for this server completes or fails.',
],
'backup_scheduled' => [
'label' => 'Scheduled Backup Notifications',
'helper' => 'Receive a notification and email when a scheduled backup for this server completes or fails.',
],
],
'reinstall' => [
'title' => 'Reinstall Server',
'body' => 'Reinstalling your server will stop it, and then re-run the installation script that initially set it up.',

View File

@@ -0,0 +1,14 @@
<?php
return [
'model_label' => 'Hosts de copia de seguridad',
'name' => 'Nombre',
'schema' => 'Esquema',
'backups' => 'Copias de seguridad',
'linked_nodes' => 'Nodos vinculados',
'all_nodes' => 'Todos los nodos',
'configuration' => 'Configuración',
'no_configuration' => 'No se requiere configuración adicional',
'no_backup_hosts' => 'No hay hosts de copia de seguridad',
'local_backups_only' => 'Todas las copias de seguridad se crearán localmente en el nodo correspondiente',
];

View File

@@ -1,9 +1,9 @@
<?php
return [
'nav_title' => 'Hosts de base de datos',
'nav_title' => 'Bases de datos',
'model_label' => 'Host de base de datos',
'model_label_plural' => 'Hosts de base de datos',
'model_label_plural' => 'Bases de datos',
'table' => [
'database' => 'Base de datos',
'name' => 'Nombre',
@@ -13,20 +13,20 @@ return [
'username' => 'Nombre de usuario',
'password' => 'Contraseña',
'remote' => 'Conexiones desde',
'remote_helper' => 'Desde donde se deben permitir las conexiones. Dejar en blanco para permitir conexiones desde cualquier lugar.',
'remote_helper' => 'Desde dónde se deben permitir las conexiones. Déjalo en blanco para permitir conexiones desde cualquier lugar.',
'max_connections' => 'Número máximo de conexiones',
'created_at' => 'Se creó a la(s)',
'created_at' => 'Creado el',
'connection_string' => 'Cadena de conexión JDBC',
],
'error' => 'Error al conectar al host',
'host' => 'Host',
'host_help' => 'La dirección IP o nombre de dominio que debe ser usado cuando se intenta conectar a este host MySQL desde este Panel para crear nuevas bases de datos.',
'host_help' => 'La dirección IP o nombre de dominio que debe ser usado cuando se intenta conectar a este host MySQL desde este panel para crear nuevas bases de datos.',
'port' => 'Puerto',
'port_help' => 'El puerto en el que MySQL se está ejecutando para este host.',
'max_database' => 'Número máximo de bases de datos',
'max_databases_help' => 'El número máximo de bases de datos que pueden ser creadas en este host. Si se alcanza el límite, no se pueden crear nuevas bases de datos en este host. En blanco es ilimitado.',
'display_name' => 'Mostrar Nombre',
'display_name_help' => 'Un identificador corto usado para distinguir esta ubicación de otros. Debe tener entre 1 y 60 caracteres, por ejemplo, us.nyc.lvl3.',
'max_databases_help' => 'El número máximo de bases de datos que se pueden crear en este host. Si se alcanza el límite, no se podrán crear nuevas bases de datos en este host. Déjalo en blanco para que sea ilimitado.',
'display_name' => 'Nombre visible',
'display_name_help' => 'La dirección IP o el nombre de dominio que se mostrará al usuario final.',
'username' => 'Nombre de usuario',
'username_help' => 'El nombre de usuario que tiene permisos suficientes para crear nuevos usuarios y bases de datos en el sistema.',
'password' => 'Contraseña',
@@ -35,27 +35,29 @@ return [
'linked_nodes_help' => 'Esta configuración se establece por defecto en este host de base de datos cuando se añade una base de datos a un servidor en el nodo seleccionado.',
'connection_error' => 'Error al conectar al host de base de datos',
'no_database_hosts' => 'No hay hosts de base de datos',
'no_databases' => 'No hay bases de datos',
'no_nodes' => 'No hay nodos',
'delete_help' => 'Este Host de base de datos tiene bases de datos',
'nodes' => 'Nodos',
'delete_help' => 'Este host de base de datos tiene bases de datos',
'unlimited' => 'Ilimitado',
'anywhere' => 'Cualquier lugar',
'rotate' => 'Rotar',
'rotate_password' => 'Renovar Contraseña',
'rotate_password' => 'Renovar contraseña',
'rotated' => 'Contraseña renovada',
'rotate_error' => 'Error al renovar la contraseña',
'databases' => 'Bases de Datos',
'databases' => 'Bases de datos',
'setup' => [
'preparations' => 'Preparativos',
'database_setup' => 'Configuración de la base de datos',
'panel_setup' => 'Configuración del Panel',
'panel_setup' => 'Configuración del panel',
'note' => 'Actualmente, ¡solo bases de datos MySQL/ MariaDB están soportadas para hosts de bases de datos!',
'different_server' => '¿El panel y la base de datos <i>no</i> están en el mismo servidor?',
'database_user' => 'Usuario de la base de datos',
'cli_login' => 'Utilice <code>mysql -u root -p</code> para acceder al cli de mysql.',
'cli_login' => 'Usa <code>mysql -u root -p</code> para acceder a la CLI de MySQL.',
'command_create_user' => 'Comando para crear el usuario',
'command_assign_permissions' => 'Comando para asignar permisos',
'cli_exit' => 'Para salir del cli de mysql, ejecuta <code>exit</code>.',

72
lang/es/admin/plugin.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
return [
'nav_title' => 'Plugins',
'model_label' => 'Plugin',
'model_label_plural' => 'Plugins',
'name' => 'Nombre',
'update_available' => 'Hay una actualización disponible para este plugin',
'author' => 'Autor',
'version' => 'Versión',
'category' => 'Categoría',
'status' => 'Estado',
'visit_website' => 'Visita el sitio web',
'settings' => 'Ajustes',
'install' => 'Instalar',
'uninstall' => 'Desinstalar',
'update' => 'Actualizar',
'enable' => 'Activar',
'disable' => 'Desactivar',
'import_from_file' => 'Importar desde archivo',
'import_from_url' => 'Importar desde URL',
'file' => 'Archivo',
'no_plugins' => 'No hay plugins',
'all' => 'Todos',
'change_load_order' => 'Cambiar orden de carga',
'apply_load_order' => 'Aplicar orden de carga',
'enable_theme_modal' => [
'heading' => 'El tema ya está activado',
'description' => 'Ya tienes un tema activado. Activar varios temas puede provocar errores visuales. ¿Quieres continuar?',
],
'status_enum' => [
'not_installed' => 'No instalado',
'disabled' => 'Desactivado',
'enabled' => 'Activado',
'errored' => 'Fallido',
'incompatible' => 'Incompatible',
],
'category_enum' => [
'plugin' => 'Plugin',
'theme' => 'Tema',
'language' => 'Paquete de idioma',
],
'notifications' => [
'goto_plugins' => 'Ir a Plugins',
'background_info' => 'Este proceso puede tardar unos segundos. Serás notificado una vez que haya terminado.',
'install_started' => 'La instalación del plugin ha comenzado en segundo plano',
'installed' => 'Plugin instalado',
'install_error' => 'No se ha podido instalar el plugin',
'uninstall_started' => 'La instalación del plugin ha comenzado en segundo plano',
'uninstalled' => 'Plugin desinstalado',
'uninstall_error' => 'No se ha podido desinstalar el plugin',
'update_started' => 'La actualización del plugin ha comenzado en segundo plano',
'updated' => 'Plugin actualizado',
'update_error' => 'No se ha podido actualizar el plugin',
'enabled' => 'Plugin activado',
'disabled' => 'Plugin desactivado',
'deleted' => 'Plugin eliminado',
'imported' => 'Plugin importado',
'import_exists' => 'Ya existe un plugin con ese id',
'import_failed' => 'No se ha podido importar el plugin',
],
];

View File

@@ -9,9 +9,41 @@ return [
'permissions' => 'Permisos',
'in_use' => 'En uso',
'all' => 'Todos',
'root_admin' => 'El rol :role tiene todos los permisos',
'root_admin_delete' => 'No se puede eliminar el Administrador raíz',
'root_admin' => 'El rol :role tiene todos los permisos.',
'root_admin_delete' => 'No es posible eliminar el administrador raíz',
'users' => 'Usuarios',
'nodes' => 'Nodos',
'nodes_hint' => 'Dejar vacío para permitir el acceso a todos los nodos',
'nodes' => 'Nodes',
'nodes_hint' => 'Déjalo vacío para permitir el acceso a todos los nodos.',
// Permission section headings (RolePermissionModels enum + special permission groups)
'models' => [
'apiKey' => 'Clave API',
'allocation' => 'Asignación',
'databaseHost' => 'Host de la base de datos',
'database' => 'Base de datos',
'egg' => 'Huevo',
'mount' => 'Montar',
'node' => 'Nodo',
'role' => 'Rol',
'server' => 'Servidor',
'user' => 'Usuario',
'webhook' => 'Vincular Webhook',
'settings' => 'Configuración',
'health' => 'Estado del sistema',
'activityLog' => 'Registros de Actividad',
'panelLog' => 'Registros del Panel',
'plugin' => 'Extensión',
],
// Permission checkbox labels (RolePermissionPrefixes enum + model-specific/special prefixes)
'permissions_list' => [
'viewList' => 'Ver lista',
'view' => 'Ver',
'create' => 'Crear',
'update' => 'Actualizar',
'delete' => 'Eliminar',
'import' => 'Importar',
'export' => 'Exportar',
'seeIps' => 'Ver IP',
],
];

View File

@@ -6,19 +6,24 @@ return [
'model_label_plural' => 'Webhooks',
'endpoint' => 'Endpoint',
'description' => 'Descripción',
'no_webhooks' => 'Sin Webhooks',
'name' => 'Nombre',
'type' => 'Tipo',
'server' => 'Servidor',
'information' => 'Información',
'payload' => 'Carga útil',
'events' => 'Eventos',
'no_webhooks' => 'Sin webhooks',
'help' => 'Ayuda',
'help_text' => 'Debes encerrar el nombre de la variable entre {{ }}, por ejemplo, si quieres obtener el nombre desde la API, puedes usar {{name}}.',
'help_text' => 'Debes encerrar el nombre de la variable entre {{ }}. Por ejemplo, si quieres obtener el nombre desde la API, puedes usar {{name}}.',
'test_now' => 'Probar ahora',
'test_now_help' => 'Esto disparará un evento `created: Server`.',
'test_now_help' => 'Esto ejecutará el evento `Creado: Servidor`',
'table' => [
'description' => 'Descripción',
'endpoint' => 'Endpoint',
],
'headers' => 'Encabezados',
'events' => 'Eventos',
'regular' => 'Regular',
'reset_headers' => 'Restablecer cabeceras',
'reset_headers' => 'Restablecer encabezados',
'discord' => 'Discord',
'discord_message' => [
'profile' => 'Perfil',
@@ -26,38 +31,38 @@ return [
'username' => 'Nombre de usuario',
'avatar_url' => 'URL del avatar',
'forum_thread' => 'Nombre del hilo del foro',
'supress_embeds' => 'Suprimir Embeds',
'supress_embeds' => 'Suprimir embeds',
'supress_embeds_text' => 'No incluyas ningún embed al serializar este mensaje',
'supress_notifications' => 'Suprimir notificaciones',
'supress_notifications_text' => 'Este mensaje no activará notificaciones push y de escritorio',
],
'discord_embed' => [
'add_embed' => 'Añadir Embed',
'flags' => 'Banderas',
'thumbnail' => 'URL de la Miniatura',
'add_embed' => 'Añadir embed',
'flags' => 'Indicadores',
'thumbnail' => 'URL de la miniatura',
'embeds' => 'Embeds',
'thread_name' => 'Nombre del hilo del foro',
'allowed_mentions' => 'Menciones permitidas',
'roles' => 'Roles',
'users' => 'usuarios',
'users' => 'Usuarios',
'everyone' => '@everyone & @here',
'author' => 'Autor',
'author_url' => 'URL del Autor',
'author_icon_url' => 'URL del icono del autor',
'body' => 'Contenido',
'title' => 'Título',
'color' => 'Color del Embed',
'color' => 'Color del embed',
'url' => 'URL',
'images' => 'Imágenes',
'image_url' => 'URL de la imágen',
'image_thumbnail' => 'URL de la Miniatura',
'image_url' => 'URL de la imagen',
'image_thumbnail' => 'URL de la miniatura',
'footer' => 'Pie de página',
'has_timestamp' => 'Tiene fecha y hora',
'footer_icon_url' => 'URL del icono de pie de página',
'add_field' => 'Añadir campo',
'fields' => 'Campos',
'field_name' => 'Nombre del Campo',
'field_value' => 'Valor del Campo',
'field_name' => 'Nombre del campo',
'field_value' => 'Valor del campo',
'inline_field' => 'Campo en línea',
],
];

View File

@@ -4,23 +4,23 @@ return [
'daemon_connection_failed' => 'Se produjo una excepción al intentar comunicarse con el daemon, lo que resultó en un código de respuesta HTTP/:code. Esta excepción ha sido registrada.',
'node' => [
'servers_attached' => 'Un nodo no debe tener servidores vinculados a él para poder ser eliminado.',
'error_connecting' => 'Error al conectarse a :node',
'daemon_off_config_updated' => 'La configuración del daemon <strong>se ha actualizado</strong>, sin embargo, se encontró un error al intentar actualizar automáticamente el archivo de configuración en el daemon. Deberás actualizar manualmente el archivo de configuración (config.yml) para que el demonio aplique estos cambios.',
'error_connecting' => 'Error al conectarse con :node',
'daemon_off_config_updated' => 'La configuración del daemon <strong>se ha actualizado</strong>, sin embargo, se encontró un error al intentar actualizar automáticamente el archivo de configuración en el daemon. Deberás actualizar manualmente el archivo de configuración (config.yml) para que el daemon aplique estos cambios.',
],
'allocations' => [
'server_using' => 'Actualmente hay un servidor utilizando esta asignación. Una asignación solo puede ser eliminada si ningún servidor está utilizándola actualmente.',
'server_using' => 'Actualmente hay un servidor usando esta asignación. Una asignación solo puede eliminarse si ningún servidor la está usando.',
'too_many_ports' => 'Agregar más de 1000 puertos en un solo rango a la vez no está soportado.',
'invalid_mapping' => 'El mapeo proporcionado para el puerto :port no era válido y no pudo ser procesado.',
'cidr_out_of_range' => 'La notación CIDR solo permite máscaras entre /25 y /32.',
'port_out_of_range' => 'Los puertos en una asignación deben ser mayores o iguales que 1024 y menores o iguales a 65535.',
],
'egg' => [
'delete_has_servers' => 'Un Huevo con servidores activos vinculados a él no puede ser eliminado del Panel.',
'invalid_copy_id' => 'El Huevo seleccionado para copiar un script no existe o está copiando un script en sí mismo.',
'has_children' => 'Este Huevo es parte de uno o más Huevos. Por favor, elimina esos Huevos antes de eliminar este Huevo.',
'delete_has_servers' => 'Un egg con servidores activos vinculados a él no puede ser eliminado del panel.',
'invalid_copy_id' => 'El egg seleccionado para copiar un script no existe o está copiando un script en sí mismo.',
'has_children' => 'Este egg es padre de uno o más eggs. Por favor, elimina esos eggs antes de eliminar este egg.',
],
'variables' => [
'env_not_unique' => 'La variable de entorno :name debe ser única para este Huevo.',
'env_not_unique' => 'La variable de entorno :name debe ser única para este egg.',
'reserved_name' => 'La variable de entorno :name está protegida y no se puede asignar a una variable.',
'bad_validation_rule' => 'La regla de validación ":rule" no es una regla válida para esta aplicación.',
],
@@ -32,7 +32,7 @@ return [
'subusers' => [
'editing_self' => 'No está permitido editar tu propia cuenta de subusuario.',
'user_is_owner' => 'No puedes agregar al propietario del servidor como subusuario para este servidor.',
'subuser_exists' => 'Ya hay un usuario con esa dirección de correo electrónico asignado como subusuario para este servidor.',
'subuser_exists' => 'Ya hay un usuario con esa dirección de correo asignado como subusuario para este servidor.',
],
'databases' => [
'delete_has_databases' => 'No se puede eliminar un servidor de base de datos que tiene bases de datos activas vinculadas a él.',
@@ -46,7 +46,7 @@ return [
'users' => [
'is_self' => 'No se puede eliminar tu propia cuenta de usuario.',
'has_servers' => 'No se puede eliminar un usuario con servidores activos asociados a su cuenta. Por favor, elimina sus servidores antes de continuar.',
'node_revocation_failed' => 'Error al revocar las claves en <a href=":link">Nodo #:node</a>. :error',
'node_revocation_failed' => 'Error al revocar las claves en <a href=":link">Node #:node</a>. :error',
],
'deployment' => [
'no_viable_nodes' => 'No se encontraron nodos que satisfagan los requisitos especificados para el despliegue automático.',
@@ -60,5 +60,11 @@ return [
],
'server' => [
'marked_as_failed' => 'Este servidor aún no ha completado el proceso de instalación, por favor inténtalo de nuevo más tarde.',
'file_too_large' => 'El archivo que está intentando abrir es demasiado largo para ver en el editor de archivos.',
'state_conflict' => 'Este servidor está actualmente en un estado no compatible, por favor inténtalo de nuevo más tarde.',
'suspended' => 'Este servidor está actualmente suspendido y la función solicitada no se encuentra disponible.',
'maintenance' => 'El nodo de este servidor está actualmente en mantenimiento y la funcionalidad solicitada no se encuentra disponible.',
'restoring_backup' => 'Este servidor está restaurándose desde una copia de seguridad, por favor inténtalo de nuevo más tarde.',
'transferring' => 'Este servidor está siendo transferido a una nueva máquina, por favor inténtalo de nuevo más tarde.',
],
];

19
lang/es/passkeys.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
return [
'authenticate_using_passkey' => 'Autenticar usando una llave de acceso',
'create' => 'Crear',
'delete' => 'Eliminar',
'error_something_went_wrong_generating_the_passkey' => 'Algo salió mal al generar la llave de acceso',
'invalid' => 'Llave de acceso inválida',
'last_used' => 'Último uso',
'name' => 'Nombre',
'name_placeholder' => 'Mi llave de acceso',
'no_passkeys_registered' => 'No hay llaves de acceso registradas',
'not_used_yet' => 'Aún no utilizado',
'passkeys' => 'Llave de acceso',
'description' => 'Las contraseñas le permiten iniciar sesión sin necesidad de una contraseña. En lugar de una contraseña, puede generar una clave de acceso que se almacenará en 1Password, aplicación de contraseña macOS o una aplicación alternativa en su sistema operativo favorito.',
'created_notification_title' => 'Tu llave de acceso ha sido creada',
'deleted_notification_title' => 'Tu llave de acceso ha sido eliminada',
'registration_failed_notification_title' => 'Hubo un error al registrar tu llave de acceso.',
];

View File

@@ -11,51 +11,52 @@ return [
'keys' => 'Claves',
'2fa' => '2FA',
'customization' => 'Personalización',
'passkeys' => 'Llave de acceso',
],
'username' => 'Nombre de usuario',
'admin' => 'Administrador',
'exit_admin' => 'Salir de Admin',
'exit_admin' => 'Salir del panel de administración',
'server_list' => 'Lista de servidores',
'email' => 'Correo electrónico',
'email' => 'Correo',
'password' => 'Contraseña',
'current_password' => 'Contraseña Actual',
'password_confirmation' => 'Confirmación de Contraseña',
'current_password' => 'Contraseña actual',
'password_confirmation' => 'Confirmación de contraseña',
'timezone' => 'Zona horaria',
'language' => 'Idioma',
'language_help' => '¡Tu idioma :state no ha sido traducido aún!',
'language_help' => '¡Tu idioma :state aún no ha sido traducido!',
'link' => 'Vincular :name',
'unlink' => 'Desvincular :name',
'unlinked' => ':name desvinculado',
'scan_qr' => 'Escanear código QR',
'code' => 'Código',
'setup_key' => 'Clave de configuración',
'setup_key' => 'Clave de configuración: :secret',
'invalid_code' => 'Código 2FA no válido',
'code_help' => 'Escanea el código QR de arriba usando tu aplicación de autenticación en dos pasos, luego introduce el código generado.',
'2fa_enabled' => 'La autentificación de dos factores está habilitada.',
'2fa_enabled' => 'La autenticación de dos factores está habilitada.',
'backup_help' => '¡No se volverán a mostrar!',
'backup_codes' => 'Códigos de recuperación',
'disable_2fa' => 'Deshabilitar 2FA',
'disable_2fa_help' => 'Introduzca su código 2FA actual para deshabilitar la autenticación de dos factores',
'disable_2fa_help' => 'Introduce tu código 2FA actual para deshabilitar la autenticación de dos factores',
'api_keys' => 'Claves API',
'create_api_key' => 'Crear clave API',
'api_key_created' => 'Clave API creada',
'description' => 'Descripción',
'allowed_ips' => 'IPs permitidas',
'allowed_ips_help' => 'Pulse enter para añadir una nueva dirección IP o dejar en blanco para permitir cualquier dirección IP',
'allowed_ips_help' => 'Pulsa enter para añadir una nueva dirección IP o dejar en blanco para permitir cualquier dirección IP',
'ssh_keys' => 'Claves SSH',
'create_ssh_key' => 'Crear clave SSH',
'ssh_key_created' => 'Clave SSH creada',
'name' => 'Nombre',
'public_key' => 'Clave pública',
'could_not_create_ssh_key' => 'No fue posible crear la clave SSH',
'dashboard' => 'Panel de Control',
'dashboard_layout' => 'Diseño del tablero',
'could_not_create_ssh_key' => 'No ha sido posible crear la clave SSH',
'dashboard' => 'Panel de control',
'dashboard_layout' => 'Diseño del panel',
'console' => 'Consola',
'grid' => 'Cuadrícula',
'table' => 'Tabla',
'rows' => 'Filas',
'font_size' => 'Tamaño de fuente',
'font' => 'Tipografía',
'font' => 'Fuente',
'font_preview' => 'Previsualización de fuente',
'seconds' => 'Segundos',
'graph_period' => 'Período gráfico',
@@ -63,8 +64,14 @@ return [
'navigation' => 'Tipo de navegación',
'sidebar' => 'Barra lateral',
'topbar' => 'Barra superior',
'mixed' => 'Mezclado',
'mixed' => 'Mixto',
'button_style' => 'Estilo del botón',
'icon' => 'Icono',
'icon_button' => 'Botón del icono',
'redirect_to_admin' => 'Redirigir a admin al iniciar sesión',
'redirect_to_admin_help' => 'Cuando esté activado, serás redirigido al área de administración después de iniciar sesión en lugar de la lista de servidores.',
'no_oauth' => 'No hay cuentas vinculadas',
'no_api_keys' => 'No hay claves API',
'no_ssh_keys' => 'No hay claves SSH',
'activity_info' => 'Mostrando los últimos 50 registros de actividad',
];

View File

@@ -0,0 +1,46 @@
<?php
return [
'restart_now' => 'El servidor se reiniciará ahora',
'close' => 'Cerrar',
'eula' => [
'heading' => 'EULA de Minecraft',
'description' => 'Apretando "Acepto" debajo indicas tu acuerdo con el <x-filament::link href="https://minecraft.net/eula" target="_blank">EULA </x-filament::link> de Minecraft.',
'accept' => 'Estoy de acuerdo',
'accepted' => 'EULA de Minecraft aceptado',
'failed' => 'No se pudo aceptar el EULA de Minecraft',
],
'gsl_token' => [
'heading' => 'Token GSL inválido',
'description' => 'Parece que su token de inicio de sesión de Gameserver (token GSL) no es válido o ha caducado.',
'submit' => 'Actualizar token GSL',
'info' => 'Puedes <x-filament::link href="https://steamcommunity.com/dev/managegameservers" target="_blank">generar uno nuevo</x-filament::link> e introducirlo a continuación, o bien dejar el campo vacío para eliminarlo por completo.',
'updated' => 'Token GSL actualizado',
'failed' => 'No se pudo actualizar el token GSL',
],
'java_version' => [
'heading' => 'Versión de Java no compatible',
'description' => 'Este servidor está ejecutando actualmente una versión no soportada de Java y no se puede iniciar.',
'submit' => 'Actualizar imagen de Docker',
'select_version' => 'Por favor, seleccione una versión soportada de la lista de abajo para continuar iniciando el servidor.',
'docker_image' => 'Imagen de Docker',
'updated' => 'Imagen de Docker actualizada.',
'failed' => 'No se pudo actualizar la imagen de Docker',
],
'pid_limit' => [
'heading_admin' => 'Límite de memoria o procesos alcanzado...',
'heading_user' => 'Posible límite de recursos alcanzado...',
'description_admin' => '<p>Este servidor ha alcanzado el límite máximo de procesos o de memoria.</p><p class="mt-4">Aumentar <code>container_pid_limit</code> en la configuración de Wings, <code>config.yml</code>, podría ayudar a resolver este problema.</p><p class="mt-4"><b>Nota: Es necesario reiniciar Wings para que los cambios en el archivo de configuración surtan efecto.</b></p>',
'description_user' => '<p>Este servidor está intentando utilizar más recursos de los asignados. Por favor, contacte al administrador y envíale el siguiente error.</p><p class="mt-4"><code>pthread_create falló; es posible que se haya agotado la memoria o que se hayan alcanzado los límites de procesos o recursos.</code></p>',
],
'steam_disk_space' => [
'heading' => 'Sin espacio en disco...',
'description_admin' => '<p>Este servidor se ha quedado sin espacio en disco disponible y no puede completar el proceso de instalación o actualización.</p><p class="mt-4">Asegúrese de que la máquina disponga de suficiente espacio en disco ejecutando el comando <code class="rounded py-1 px-2">df -h</code> en la máquina que aloja este servidor. Elimine archivos o aumente el espacio en disco disponible para solucionar el problema.</p>',
'description_user' => '<p>Este servidor se ha quedado sin espacio en disco disponible y no puede completar el proceso de instalación o actualización. Por favor, póngase en contacto con el administrador o el/los administrador(es) e infórmeles sobre los problemas de espacio en disco.</p>',
],
];

View File

@@ -12,6 +12,7 @@ return [
'cron' => 'Cron',
'status' => 'Estado',
'schedule_status' => [
'new' => 'Nuevo',
'inactive' => 'Inactivo',
'processing' => 'Procesando',
'active' => 'Activo',
@@ -19,17 +20,17 @@ return [
'no_tasks' => 'No hay tareas',
'run_now' => 'Ejecutar ahora',
'online_only' => 'Solo cuando esté iniciado',
'last_run' => 'Última Ejecución',
'next_run' => 'Próxima Ejecución',
'last_run' => 'Última ejecución',
'next_run' => 'Próxima ejecución',
'never' => 'Nunca',
'cancel' => 'Cancelar',
'only_online' => '¿Sólo cuando el servidor esté iniciado?',
'only_online_hint' => 'Solo ejecutar este programa cuando el servidor esté en ejecución',
'enabled' => '¿Habilitar programación?',
'enabled_hint' => 'Esta programación se ejecutará automáticamente si está habilitada.',
'only_online' => '¿Solo cuando el servidor esté iniciado?',
'only_online_hint' => 'Solo ejecutar esta programación cuando el servidor esté en ejecución.',
'enabled' => '¿Activar programación?',
'enabled_hint' => 'Esta programación se ejecutará automáticamente si está activada.',
'cron_body' => 'Por favor, tenga en cuenta que las entradas de cron a continuación siempre asumen UTC.',
'cron_body' => 'Ten en cuenta que las entradas de cron a continuación siempre asumen UTC.',
'cron_timezone' => 'Siguiente ejecución en tu zona horaria (:timezone): <b> :next_run </b>',
'invalid' => 'Inválido',
@@ -77,7 +78,7 @@ return [
'action' => 'Acción',
'payload' => 'Carga útil',
'no_payload' => 'Sin carga útil',
'time_offset' => 'Diferencia Horaria',
'time_offset' => 'Diferencia horaria',
'first_task' => 'Primera tarea',
'seconds' => 'Segundo|Segundos',
'continue_on_failure' => 'Continuar en caso de error',

View File

@@ -3,9 +3,9 @@
return [
'title' => 'Usuarios',
'username' => 'Nombre de usuario',
'email' => 'Correo electrónico',
'email' => 'Correo',
'assign_all' => 'Asignar todo',
'invite_user' => 'Invitar Usuario',
'invite_user' => 'Invitar usuario',
'action' => 'Invitar',
'remove' => 'Eliminar usuario',
'edit' => 'Editar usuario',
@@ -14,36 +14,64 @@ return [
'notification_add' => '¡Usuario invitado!',
'notification_edit' => '¡Usuario actualizado!',
'notification_delete' => '¡Usuario eliminado!',
'notification_failed' => 'Error al invitar al usuario',
'notification_failed' => '¡Error al invitar al usuario!',
'permissions' => [
'title' => 'Permisos',
'activity_title' => 'Actividad',
'activity_desc' => 'Permisos que controlan el acceso del usuario a los registros de actividad del servidor.',
'startup_title' => 'Inicio',
'startup_desc' => 'Permisos que controlan la capacidad del usuario para ver los parámetros de inicio de este servidor.',
'settings_title' => 'Configuración',
'settings_desc' => 'Permisos que controlan la capacidad del usuario para modificar la configuración de este servidor.',
'control_title' => 'Control',
'control_desc' => 'Permisos que controlan la capacidad del usuario para controlar el estado de un servidor, o enviar comandos.',
'user_title' => 'Usuario',
'user_desc' => 'Permisos que permiten al usuario administrar otros subusuarios en un servidor. Nunca podrán editar su propia cuenta o asignar permisos que no tienen ellos mismos.',
'file_title' => 'Archivo',
'file_desc' => 'Permisos que controlan la capacidad del usuario para modificar el sistema de archivos de este servidor.',
'allocation_title' => 'Asignación',
'allocation_desc' => 'Permisos que controlan la capacidad del usuario de modificar las asignaciones de puertos para este servidor.',
'database_title' => 'Base de datos',
'database_desc' => 'Permisos que controlan el acceso del usuario a la administración de base de datos de este servidor.',
'backup_title' => 'Copia de seguridad',
'backup_desc' => 'Permisos que controlan la capacidad del usuario para generar y administrar copias de seguridad del servidor.',
'schedule_desc' => 'Permisos que controlan el acceso del usuario a la gestión de horarios de este servidor.',
'schedule_title' => 'Programación',
'schedule_desc' => 'Permisos que controlan el acceso del usuario a la gestión de programaciones de este servidor.',
'startup_read' => 'Permite al usuario ver las variables de inicio de un servidor.',
'startup_update' => 'Permite al usuario modificar las variables de inicio del servidor.',
'startup_docker_image' => 'Permite al usuario modificar la imagen de Docker utilizada al ejecutar el servidor.',
'settings_reinstall' => 'Permite al usuario reinstalar este servidor.',
'settings_rename' => 'Permite al usuario a renombrar este servidor.',
'settings_rename' => 'Permite al usuario renombrar este servidor.',
'settings_description' => 'Permite a un usuario cambiar la descripción de este servidor.',
'settings_reinstall' => 'Permite al usuario reinstalar este servidor.',
'settings_change_icon' => 'Permite al usuario cambiar el icono de este servidor.',
'activity_read' => 'Permite al usuario ver los registros de actividad del servidor.',
'websocket_connect' => 'Permite a un usuario el acceso al websocket para este servidor.',
'control_console' => 'Permite al usuario enviar datos a la consola del servidor.',
'control_start' => 'Permite al usuario iniciar la instancia del servidor.',
'control_stop' => 'Permite al usuario detener la instancia del servidor.',
'control_restart' => 'Permite al usuario reiniciar la instancia del servidor.',
'control_kill' => 'Permite al usuario matar la instancia del servidor.',
'control_kill' => 'Permite al usuario forzar el cierre de la instancia del servidor.',
'user_create' => 'Permite al usuario crear nuevas cuentas de usuario para el servidor.',
'user_read' => 'Permite al usuario ver los usuarios asociados con este servidor.',
'user_update' => 'Permite al usuario modificar otros usuarios asociados con este servidor.',
'user_delete' => 'Permite al usuario eliminar otros usuarios asociados con este servidor.',
'file_create' => 'Permite al usuario crear nuevos archivos y directorios.',
'file_read' => 'Permite al usuario ver los contenidos de un directorio, pero no ver los contenidos o descargar archivos.',
'file_read_content' => 'Permite al usuario ver el contenido de un archivo dado. Esto también permitirá al usuario descargar archivos.',
@@ -51,23 +79,32 @@ return [
'file_delete' => 'Permite al usuario eliminar archivos y directorios.',
'file_archive' => 'Permite al usuario crear archivos de archivos y descomprimir archivos existentes.',
'file_sftp' => 'Permite al usuario realizar las acciones de los archivos anteriores usando un cliente SFTP.',
'allocation_read' => 'Permite al usuario ver todas las asignaciones actualmente asignadas a este servidor. Los usuarios con cualquier nivel de acceso a este servidor siempre pueden ver la asignación principal.',
'allocation_update' => 'Permite al usuario cambiar la asignación principal del servidor y adjuntar notas a cada asignación.',
'allocation_delete' => 'Permite al usuario eliminar una asignación del servidor.',
'allocation_create' => 'Permite al usuario agregar asignaciones adicionales al servidor.',
'allocation_create' => 'Permite al usuario añadir asignaciones adicionales al servidor.',
'database_create' => 'Permite al usuario crear una nueva base de datos para el servidor.',
'database_read' => 'Permite al usuario acceder a las bases de datos del servidor.',
'database_update' => 'Permite al usuario realizar modificaciones en una base de datos. Si el usuario no tiene el permiso "Ver contraseña", no podrá modificar la contraseña.',
'database_delete' => 'Permite al usuario eliminar una instancia de base de datos.',
'database_view_password' => 'Permite al usuario ver una contraseña de base de datos en el sistema.',
'schedule_create' => 'Permite al usuario crear un nuevo horario para el servidor.',
'schedule_read' => 'Permite al usuario ver los horarios de un servidor.',
'schedule_update' => 'Permite al usuario realizar modificaciones en un horario existente del servidor.',
'schedule_delete' => 'Permite al usuario eliminar un horario del servidor.',
'backup_create' => 'Permite al usuario crear un nuevo horario para el servidor.',
'schedule_create' => 'Permite al usuario crear un nuevo programación para el servidor.',
'schedule_read' => 'Permite al usuario ver los programaciones de un servidor.',
'schedule_update' => 'Permite al usuario realizar modificaciones en una programación existente del servidor.',
'schedule_delete' => 'Permite al usuario eliminar un programación del servidor.',
'backup_create' => 'Permite al usuario crear nuevas copias de seguridad para el servidor.',
'backup_read' => 'Permite al usuario ver todas las copias de seguridad que existen para este servidor.',
'backup_delete' => 'Permite al usuario eliminar copias de seguridad del sistema.',
'backup_download' => 'Permite al usuario descargar una copia de seguridad para el servidor. Peligro: esto permite a un usuario acceder a todos los archivos para el servidor en la copia de seguridad.',
'backup_restore' => 'Permite al usuario restaurar una copia de seguridad del servidor. Peligro: esto permite al usuario borrar todos los archivos del servidor en el proceso.',
'mount_title' => 'Montajes',
'mount_desc' => 'Permisos que controlan la capacidad del usuario para gestionar los montajes de este servidor.',
'mount_read' => 'Permite al usuario ver la página de montajes y los montajes disponibles.',
'mount_update' => 'Permite al usuario activar o desactivar los montajes del servidor.',
],
];

View File

@@ -0,0 +1,14 @@
<?php
return [
'model_label' => 'Hôte de sauvegarde|Hôtes de sauvegarde',
'name' => 'Nom',
'schema' => 'Schéma',
'backups' => 'Sauvegardes',
'linked_nodes' => 'Nœud lié',
'all_nodes' => 'Tous les nœuds',
'configuration' => 'Configuration',
'no_configuration' => 'Aucune configuration supplémentaire n\'est requise',
'no_backup_hosts' => 'Aucun hôte de sauvegarde',
'local_backups_only' => 'Toutes les sauvegardes seront créées localement sur le noeud respectif',
];

View File

@@ -35,7 +35,9 @@ return [
'linked_nodes_help' => 'Ce paramètre nest défini par défaut que pour cet hôte de base de données lors de lajout dune base de données à un serveur sur le nœud sélectionné.',
'connection_error' => 'Erreur de connexion à lhôte de la base de données',
'no_database_hosts' => 'Aucun hôte de base de données',
'no_databases' => 'Aucune base de données',
'no_nodes' => 'Aucun noeud',
'nodes' => 'Nœuds',
'delete_help' => 'Lhôte de base de données possède des bases de données',
'unlimited' => 'Illimité',
'anywhere' => 'N\'importe où',

View File

@@ -20,6 +20,7 @@ return [
'disable' => 'Désactiver',
'import_from_file' => 'Importer depuis un fichier',
'import_from_url' => 'Importer depuis une URL',
'file' => 'Fichier',
'no_plugins' => 'Aucune extension',
'all' => 'Tout',
'change_load_order' => 'Modifier lordre de chargement',
@@ -45,17 +46,27 @@ return [
],
'notifications' => [
'goto_plugins' => 'Aller aux Plugins',
'background_info' => 'Ce processus peut prendre quelques secondes. Vous serez notifié une fois terminé.',
'install_started' => 'L\'installation du plugin a commencé en arrière-plan',
'installed' => 'Extension installée',
'install_error' => 'Impossible dinstaller lextension',
'uninstall_started' => 'Désinstallation du plugin démarrée en arrière-plan',
'uninstalled' => 'Extension désinstallée',
'uninstall_error' => 'Impossible de désinstaller lextension',
'deleted' => 'Extension supprimée',
'update_started' => 'La mise à jour du plugin a commencé en arrière-plan',
'updated' => 'Extension mise à jour',
'update_error' => 'Impossible de mettre à jour lextension',
'enabled' => 'Extension activée',
'disabled' => 'Extension désactivée',
'deleted' => 'Extension supprimée',
'imported' => 'Extension importée',
'import_exists' => 'Une extension avec cet Id existe déjà',
'import_exists' => 'Une extension avec cet id existe déjà',
'import_failed' => 'Impossible dimporter lextension',
],
];

View File

@@ -14,4 +14,36 @@ return [
'users' => 'Utilisateurs',
'nodes' => 'Nœuds',
'nodes_hint' => 'Laisser vide pour autoriser l\'accès à tous les nœuds.',
// Permission section headings (RolePermissionModels enum + special permission groups)
'models' => [
'apiKey' => 'Clé API',
'allocation' => 'Allocation',
'databaseHost' => 'Hôte de base de données',
'database' => 'Base de données',
'egg' => 'Œuf',
'mount' => 'Montage',
'node' => 'Nœud',
'role' => 'Rôle',
'server' => 'Serveur',
'user' => 'Utilisateur',
'webhook' => 'Webhook',
'settings' => 'Paramètres',
'health' => 'Santé',
'activityLog' => 'Journal d\'activité',
'panelLog' => 'Logs du Panel',
'plugin' => 'Extension',
],
// Permission checkbox labels (RolePermissionPrefixes enum + model-specific/special prefixes)
'permissions_list' => [
'viewList' => 'Afficher la liste',
'view' => 'Afficher',
'create' => 'Créer',
'update' => 'Mettre à jour',
'delete' => 'Supprimer',
'import' => 'Importer',
'export' => 'Exporter',
'seeIps' => 'Voir les adresses IP',
],
];

View File

@@ -6,17 +6,22 @@ return [
'model_label_plural' => 'Webhooks',
'endpoint' => 'Point de terminaison',
'description' => 'Description',
'name' => 'Nom',
'type' => 'Type',
'server' => 'Serveur',
'information' => 'Information',
'payload' => 'Payload',
'events' => 'Événements',
'no_webhooks' => 'Aucun webhook',
'help' => 'Aide',
'help_text' => 'Vous devez englober les noms de variables dans {{ }}. Par exemple, si vous voulez obtenir le nom depuis l\'api, vous pouvez utiliser {{name}}',
'test_now' => 'Tester maintenant',
'test_now' => 'Tester',
'test_now_help' => 'Cela va lancer l\'événement `created: Server`',
'table' => [
'description' => 'Description',
'endpoint' => 'Point de terminaison',
],
'headers' => 'En-Têtes',
'events' => 'Événements',
'regular' => 'Standard',
'reset_headers' => 'Réinitialiser les en-têtes',
'discord' => 'Discord',

View File

@@ -60,5 +60,11 @@ return [
],
'server' => [
'marked_as_failed' => 'Ce serveur n\'a pas encore terminé son processus d\'installation, veuillez réessayer plus tard.',
'file_too_large' => 'Le fichier que vous essayez d\'ouvrir est trop volumineux pour être affiché dans l\'éditeur de fichiers.',
'state_conflict' => 'Ce serveur est actuellement en état non pris en charge, veuillez réessayer plus tard.',
'suspended' => 'Ce serveur est actuellement suspendu et la fonctionnalité demandée est indisponible.',
'maintenance' => 'Le noeud de ce serveur est actuellement en maintenance et la fonctionnalité demandée est indisponible.',
'restoring_backup' => 'Ce serveur est en cours de restauration à partir d\'une sauvegarde, veuillez réessayer plus tard.',
'transferring' => 'Ce serveur est en cours de transfert vers une nouvelle machine, veuillez réessayer plus tard.',
],
];

19
lang/fr/passkeys.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
return [
'authenticate_using_passkey' => 'S\'authentifier en utilisant un mot de passe',
'create' => 'Créer',
'delete' => 'Supprimer',
'error_something_went_wrong_generating_the_passkey' => 'Une erreur s\'est produite lors de la génération du mot de passe',
'invalid' => 'Clé daccès non valide',
'last_used' => 'Dernière utilisation',
'name' => 'Nom',
'name_placeholder' => 'Ma clé d\'accès',
'no_passkeys_registered' => 'Aucun mot de passe enregistré',
'not_used_yet' => 'Pas encore utilisé',
'passkeys' => 'Clés d\'accès',
'description' => 'Les mots de passe vous permettent de vous connecter sans avoir besoin d\'un mot de passe. Au lieu d\'un mot de passe, vous pouvez générer une clé d\'accès qui sera stockée dans l\'application 1Password, mot de passe macOS, ou une application alternative sur votre OS favori.',
'created_notification_title' => 'Votre mot de passe a été créé',
'deleted_notification_title' => 'Votre mot de passe a été supprimé',
'registration_failed_notification_title' => 'L\'enregistrement du mot de passe a échoué',
];

View File

@@ -11,6 +11,7 @@ return [
'keys' => 'Clés',
'2fa' => '2FA',
'customization' => 'Personnalisation',
'passkeys' => 'Clés d\'accès',
],
'username' => 'Nom d\'utilisateur',
'admin' => 'Administrateur',
@@ -64,7 +65,13 @@ return [
'sidebar' => 'Barre latérale',
'topbar' => 'Barre d\'entête',
'mixed' => 'Mixte',
'button_style' => 'Style de bouton',
'icon' => 'Icône',
'icon_button' => 'Boutons avec icône',
'redirect_to_admin' => 'Rediriger vers la zone d\'admin à la connexion',
'redirect_to_admin_help' => 'Lorsqu\'elle est activée, vous serez redirigé vers la zone d\'admin après la connexion, au lieu de la liste des serveurs.',
'no_oauth' => 'Aucun compte lié',
'no_api_keys' => 'Aucunes clés API',
'no_ssh_keys' => 'Aucunes clés SSH',
'activity_info' => 'Affichage des 50 derniers logs d\'activité',
];

View File

@@ -0,0 +1,50 @@
<?php
return [
'restart_now' => 'Le serveur va redémarrer maintenant.',
'close' => 'Fermer',
'eula' => [
'heading' => 'CLUF Minecraft',
'description' => 'En cliquant sur « J\'accepte » ci-dessous, vous indiquez que vous acceptez le <x-filament::link href="https://minecraft.net/eula" target="_blank">CLUF de Minecraft</x-filament::link>.',
'accept' => 'J\'accepte',
'accepted' => 'CLUF Minecraft acceptée',
'failed' => 'Impossible d\'accepter le CLUF Minecraft',
],
'gsl_token' => [
'heading' => 'Jeton GSL invalide',
'description' => 'Il semble que votre jeton de connexion au serveur de jeu (jeton GSL) soit invalide ou a expiré.',
'submit' => 'Mettre à jour le jeton GSL',
'info' => 'Vous pouvez soit <x-filament::link href="https://steamcommunity.com/dev/managegameservers" target="_blank">générer un nouveau</x-filament::link> et le saisir ci-dessous ou laisser le champ vide pour le supprimer complètement.',
'updated' => 'Jeton GSL mis à jour',
'failed' => 'Impossible de mettre à jour le jeton GSL',
],
'java_version' => [
'heading' => 'Version Java non prise en charge',
'description' => 'Ce serveur utilise actuellement une version non prise en charge de Java et ne peut pas être démarré.',
'submit' => 'Mettre à jour l\'image de Docker',
'select_version' => 'Veuillez sélectionner une version prise en charge dans la liste ci-dessous pour continuer à démarrer le serveur.',
'docker_image' => 'Image Docker',
'updated' => 'Image Docker mise à jour',
'failed' => 'Impossible de mettre à jour l\'image du docker',
],
'pid_limit' => [
'heading_admin' => 'Mémoire ou limite de processus atteinte ...',
'heading_user' => 'Limite possible de ressources atteinte...',
'description_admin' => '<p>Ce serveur a atteint la limite maximale de processus ou de mémoire.</p>
<p class="mt-4">Augmenter <code>container_pid_limit</code> dans la configuration de Wings, <code>config.yml</code>, peut aider à résoudre ce problème.</p>
<p class="mt-4"><b>Remarque : Wings doit être redémarré pour que les modifications du fichier de configuration prennent effet</b></p>',
'description_user' => '<p>Ce serveur tente dutiliser plus de ressources que celles qui lui sont allouées. Veuillez contacter ladministrateur et lui transmettre lerreur ci-dessous.</p>
<p class="mt-4"><code>pthread_create a échoué, probablement en raison dun manque de mémoire ou de limites de processus/ressources atteintes</code></p>',
],
'steam_disk_space' => [
'heading' => 'Espace disque insuffisant...',
'description_admin' => '<p>Ce serveur na plus despace disque disponible et ne peut pas terminer le processus dinstallation ou de mise à jour.</p>
<p class="mt-4">Assurez-vous que la machine dispose de suffisamment despace disque en tapant <code class="rounded py-1 px-2">df -h</code> sur la machine hébergeant ce serveur. Supprimez des fichiers ou augmentez lespace disque disponible pour résoudre le problème.</p>',
'description_user' => '<p>Ce serveur na plus despace disque disponible et ne peut pas terminer le processus dinstallation ou de mise à jour. Veuillez contacter ladministrateur(s) et linformer des problèmes despace disque.</p>',
],
];

View File

@@ -12,6 +12,7 @@ return [
'cron' => 'Cron',
'status' => 'Statut',
'schedule_status' => [
'new' => 'Nouveau',
'inactive' => 'Inactif',
'processing' => 'Traitement en cours',
'active' => 'Actif',

View File

@@ -17,33 +17,61 @@ return [
'notification_failed' => 'Impossible d\'inviter l\'utilisateur !',
'permissions' => [
'title' => 'Permissions',
'activity_title' => 'Activité',
'activity_desc' => 'Autorisations qui contrôlent l\'accès d\'un utilisateur aux journaux d\'activité du serveur.',
'startup_title' => 'Démarrage',
'startup_desc' => 'Autorisations qui contrôlent la capacité d\'un utilisateur à voir les paramètres de démarrage de ce serveur.',
'settings_title' => 'Paramètres',
'settings_desc' => 'Autorisations qui contrôlent la capacité d\'un utilisateur à voir les paramètres de démarrage de ce serveur.',
'control_title' => 'Contrôle',
'control_desc' => 'Autorisations qui contrôlent la capacité d\'un utilisateur à contrôler l\'état de puissance d\'un serveur, ou envoyer des commandes.',
'user_title' => 'Utilisateur',
'user_desc' => 'Permissions qui permettent à un utilisateur de gérer d\'autres sous-utilisateurs sur un serveur. Ils ne pourront jamais modifier leur propre compte ou assigner des autorisations qu\'ils n\'ont pas eux-mêmes.',
'file_title' => 'Fichier',
'file_desc' => 'Autorisations qui contrôlent la possibilité pour un utilisateur de modifier le système de fichiers pour ce serveur.',
'allocation_title' => 'Allocation',
'allocation_desc' => 'Autorisations qui contrôlent la possibilité pour un utilisateur de modifier les allocations de port pour ce serveur.',
'database_title' => 'Base de données',
'database_desc' => 'Autorisations qui contrôlent l\'accès d\'un utilisateur à la gestion de la base de données pour ce serveur.',
'backup_title' => 'Sauvegarde',
'backup_desc' => 'Autorisations qui contrôlent la capacité d\'un utilisateur à générer et gérer des sauvegardes de serveur.',
'schedule_title' => 'Planifier',
'schedule_desc' => 'Autorisations qui contrôlent l\'accès d\'un utilisateur à la gestion des programmations pour ce serveur.',
'startup_read' => 'Permet à un utilisateur de voir les variables de démarrage d\'un serveur.',
'startup_update' => 'Permet à un utilisateur de voir les variables de démarrage d\'un serveur.',
'startup_docker_image' => 'Permet à un utilisateur de modifier l\'image Docker utilisée lors de l\'exécution du serveur.',
'settings_reinstall' => 'Permet à un utilisateur de déclencher une réinstallation de ce serveur.',
'settings_rename' => 'Permet à un utilisateur de renommer et de modifier la description de ce serveur',
'settings_description' => 'Permet à un utilisateur de changer la description de ce serveur.',
'settings_reinstall' => 'Permet à un utilisateur de déclencher une réinstallation de ce serveur.',
'settings_change_icon' => 'Permet à un utilisateur de modifier l\'icône de ce serveur.',
'activity_read' => 'Permet à un utilisateur de voir les journaux d\'activité du serveur.',
'websocket_connect' => 'Permet à un utilisateur d\'accéder à la Websocket pour ce serveur.',
'control_console' => 'Permet à un utilisateur d\'envoyer des données à la console du serveur.',
'control_start' => 'Permet à un utilisateur de démarrer l\'instance du serveur.',
'control_stop' => 'Permet à un utilisateur d\'arrêter l\'instance du serveur.',
'control_restart' => 'Permet à un utilisateur de redémarrer l\'instance du serveur.',
'control_kill' => 'Permet à un utilisateur de tuer l\'instance du serveur.',
'user_create' => 'Permet à un utilisateur de créer de nouveaux comptes utilisateur pour le serveur.',
'user_read' => 'Autorise l\'utilisateur à voir les utilisateurs associés à ce serveur.',
'user_update' => 'Autorise l\'utilisateur à modifier les autres utilisateurs associés à ce serveur.',
'user_delete' => 'Autorise l\'utilisateur à supprimer les autres utilisateurs associés à ce serveur.',
'file_create' => 'Autorise l\'utilisateur à créer de nouveaux fichiers et dossiers.',
'file_read' => 'Permet à un utilisateur de visualiser le contenu d\'un répertoire, mais pas de visualiser le contenu ou de télécharger des fichiers.',
'file_read_content' => 'Permet à un utilisateur de visualiser le contenu d\'un fichier donné. Cela permettra également à l\'utilisateur de télécharger des fichiers.',
@@ -51,23 +79,32 @@ return [
'file_delete' => 'Permet à un utilisateur de supprimer des fichiers et des répertoires.',
'file_archive' => 'Permet à un utilisateur de créer des archives de fichiers et de décompresser des archives existantes.',
'file_sftp' => 'Permet à un utilisateur d\'effectuer les actions de fichier ci-dessus en utilisant un client SFTP.',
'allocation_read' => 'Permet à un utilisateur de voir toutes les allocations actuellement assignées à ce serveur. Les utilisateurs ayant n\'importe quel niveau d\'accès à ce serveur peuvent toujours voir l\'allocation principale.',
'allocation_update' => 'Permet à un utilisateur de modifier l\'allocation principale du serveur et d\'attacher des notes à chaque allocation.',
'allocation_delete' => 'Permet à un utilisateur de supprimer une allocation du serveur.',
'allocation_create' => 'Permet à un utilisateur d\'affecter des allocations supplémentaires au serveur.',
'database_create' => 'Autorise un utilisateur à créer une nouvelle base de données pour le serveur.',
'database_read' => 'Autorise un utilisateur à voir les bases de données du serveur.',
'database_update' => 'Autorise un utilisateur à modifier une base de données. Si l\'utilisateur n\'a pas la permission "Voir le mot de passe", il ne sera pas en mesure de modifier le mot de passe.',
'database_delete' => 'Autorise un utilisateur à supprimer une base de données.',
'database_view_password' => 'Autorise un utilisateur à visualiser un mot de passe de base de données.',
'schedule_create' => 'Autorise un utilisateur à créer une planification pour le serveur.',
'schedule_read' => 'Autorise un utilisateur à voir les planifications d\'un serveur.',
'schedule_update' => 'Autorise un utilisateur à apporter des modifications à une planification d\'un serveur existant.',
'schedule_delete' => 'Autorise un utilisateur à supprimer une planification pour le serveur.',
'backup_create' => 'Permet à un utilisateur de créer de nouveaux comptes utilisateur pour le serveur.',
'backup_read' => 'Permet à un utilisateur de voir toutes les sauvegardes qui existent pour ce serveur.',
'backup_delete' => 'Permet à un utilisateur de supprimer les sauvegardes du système.',
'backup_download' => 'Permet à un utilisateur de télécharger une sauvegarde pour le serveur. Danger : cela permet à un utilisateur d\'accéder à tous les fichiers du serveur dans la sauvegarde.',
'backup_restore' => 'Permet à un utilisateur de restaurer une sauvegarde pour le serveur. Danger : cela permet à l\'utilisateur de supprimer tous les fichiers du serveur.',
'mount_title' => 'Montages',
'mount_desc' => 'Autorisations qui contrôlent la capacité d\'un utilisateur à gérer les montages pour ce serveur.',
'mount_read' => 'Permet à un utilisateur de visualiser la page des montages et de voir les montages disponibles.',
'mount_update' => 'Permet à un utilisateur d\'activer/désactiver les montages pour le serveur.',
],
];

View File

@@ -1,7 +1,7 @@
<?php
return [
'heading' => 'Üdvözölk a Pelicanban!',
'heading' => 'Üdvözöllek a :app applikációban!',
'version' => 'Verzió: :version',
'advanced' => 'Haladó',
'server' => 'Szerver',
@@ -27,7 +27,7 @@ return [
'heading' => 'Nincs észlelt csomópont',
'content' => 'Úgy tűnik, hogy még nincs egyetlen csomópontod sem beállítva, de ne aggódj, mert a művelet gombra kattintva létrehozhatod az elsőt!',
'extra_note' => 'Ha bármilyen problémába ütközik, kérjük jelentse a GitHubon.',
'button_label' => 'Első csomópont létrehozása a Pelicanban',
'button_label' => 'Hozd létre az első Node-ot',
],
'intro-support' => [
'heading' => 'Pelican támogatása',

View File

@@ -35,7 +35,9 @@ return [
'linked_nodes_help' => 'Ez a beállítás csak akkor lesz alapértelmezett ennél az adatbázis-kiszolgálónál, ha egy adatbázist adunk hozzá egy szerverhez a kiválasztott csomóponton.',
'connection_error' => 'Hiba a hoszthoz való kapcsolódáskor',
'no_database_hosts' => 'Nincs adatbázis kiszolgáló',
'no_databases' => 'Nincs adatbázis',
'no_nodes' => 'Nincsenek csomópontok',
'nodes' => 'Nodes',
'delete_help' => 'Az adatbázis hoszt adatbázisokkal rendelkezik',
'unlimited' => 'Korlátlan',
'anywhere' => 'Bárhol',

72
lang/hu/admin/plugin.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
return [
'nav_title' => 'Kiegészítők',
'model_label' => 'Kiegészítő',
'model_label_plural' => 'Kiegészítők',
'name' => 'Név',
'update_available' => 'Erre a kiegészítőre elérhető egy frissítés',
'author' => 'Szerző',
'version' => 'Verzió',
'category' => 'Kategória',
'status' => 'Állapot',
'visit_website' => 'Oldal megnyitása',
'settings' => 'Beállítások',
'install' => 'Telepítés',
'uninstall' => 'Eltávolítás',
'update' => 'Frissítés',
'enable' => 'Engedélyezés',
'disable' => 'Letiltás',
'import_from_file' => 'Importálás Fájlból',
'import_from_url' => 'Importálás URL-ből',
'file' => 'Fájl',
'no_plugins' => 'Nincsenek kiegészítők',
'all' => 'Összes',
'change_load_order' => 'Betöltési sorrend megváltoztatása',
'apply_load_order' => 'Betöltési sorrend alkalmazása',
'enable_theme_modal' => [
'heading' => 'Téma már aktív',
'description' => 'Már van használatban lévő téma. Több téma egyidejű futtatása vizuális hibákat eredményezhet. Biztosan folytatni kívánja?',
],
'status_enum' => [
'not_installed' => 'Nincs telepítve',
'disabled' => 'Letiltva',
'enabled' => 'Engedélyezve',
'errored' => 'Hibás',
'incompatible' => 'Inkompatibilis',
],
'category_enum' => [
'plugin' => 'Kiegészítő',
'theme' => 'Téma',
'language' => 'Nyelvi csomag',
],
'notifications' => [
'goto_plugins' => 'Ugrás a Bővítményekhez',
'background_info' => 'Ez a folyamat néhány másodpercig tarthat. A folyamat befejezése után értesítést kap.',
'install_started' => 'A bővítmény telepítése elindult a háttérben',
'installed' => 'Telepített kiegészítő',
'install_error' => 'Kiegészítő telepítése meghíusult',
'uninstall_started' => 'A bővítmény eltávolítása elindult a háttérben',
'uninstalled' => 'Kiegészítő eltávolonítva',
'uninstall_error' => 'Kiegészítő eltávolonítása meghíusult',
'update_started' => 'A bővítmény frissítése elindult a háttérben',
'updated' => 'Kiegészítő frissítve',
'update_error' => 'Kiegészítő frissítése meghíusult',
'enabled' => 'Kiegészítő engedélyezve',
'disabled' => 'Kiegészítő letiltva',
'deleted' => 'Kiegészítő eltávolonítva',
'imported' => 'Kiegészítő importálva',
'import_exists' => 'Egy plugin ezzel az azonosítóval már létezik',
'import_failed' => 'Kiegészítő importálása sikertelen',
],
];

View File

@@ -14,4 +14,36 @@ return [
'users' => 'Felhasználók',
'nodes' => 'Csomópontok',
'nodes_hint' => 'Hagyd üresen, ha minden csomóponthoz engedélyezed a hozzáférést.',
// Permission section headings (RolePermissionModels enum + special permission groups)
'models' => [
'apiKey' => 'API Kulcs',
'allocation' => 'AllocationAllocation',
'databaseHost' => 'Adatbázis hoszt',
'database' => 'Adatbázis',
'egg' => 'Egg',
'mount' => 'Mount',
'node' => 'Node',
'role' => 'Rang',
'server' => 'Szerver',
'user' => 'Felhasználó',
'webhook' => 'Webhook',
'settings' => 'Beállítások',
'health' => 'Állapot',
'activityLog' => 'Aktivitás Napló',
'panelLog' => 'Panel Napló',
'plugin' => 'Plugin',
],
// Permission checkbox labels (RolePermissionPrefixes enum + model-specific/special prefixes)
'permissions_list' => [
'viewList' => 'Megtekintés Lista',
'view' => 'Megtekintés',
'create' => 'Létrehozás',
'update' => 'Frissítés',
'delete' => 'Törlés',
'import' => 'Importálás',
'export' => 'Exportálás',
'seeIps' => 'IP-k megtekintése',
],
];

181
lang/hu/admin/setting.php Normal file
View File

@@ -0,0 +1,181 @@
<?php
return [
'title' => 'Beállítások',
'save_success' => 'Beállítások elmentve.',
'save_failed' => 'Nem sikerült elmenteni a beállításokat',
'navigation' => [
'general' => 'Általános',
'captcha' => 'Captcha',
'mail' => 'Levelezés',
'backup' => 'Biztonsági mentés',
'oauth' => 'OAuth',
'misc' => 'Egyéb',
],
'general' => [
'app_name' => 'Alkalmazás neve',
'app_logo' => 'Alkalmazás logó',
'app_logo_help' => 'A logónak a panel gyökérkönyvtárában lévő public mappában kell lennie. Hagyd üresen, ha az alkalmazás nevét szeretnéd használni helyette.',
'app_favicon' => 'Alkalmazás ikon',
'app_favicon_help' => 'Az ikonnak a panel gyökérkönyvtárában lévő public mappában kell lennie.',
'debug_mode' => 'Hibakeresési mód',
'navigation' => 'Navigáció',
'default_navigation' => 'Alapértelmezett navigációs típus',
'sidebar' => 'Oldalsáv',
'topbar' => 'Felső sáv',
'mixed' => 'Vegyes',
'unit_prefix' => 'Mértékegység előtag',
'decimal_prefix' => 'Decimális előtag (MB/GB)',
'binary_prefix' => 'Bináris előtag (MiB/GiB)',
'2fa_requirement' => 'Kétlépcsős azonosítás kötelező',
'not_required' => 'Nem kötelező',
'admins_only' => 'Csak adminoknak kötelező',
'all_users' => 'Minden felhasználónak kötelező',
'trusted_proxies' => 'Megbízható proxyk',
'trusted_proxies_help' => 'Új IP vagy IP tartomány',
'clear' => 'Törlés',
'set_to_cf' => 'Állítsd be Cloudflare IP-kre',
'display_width' => 'Megjelenítési szélesség',
'avatar_provider' => 'Profilkép szolgáltató',
'uploadable_avatars' => 'Engeded, hogy a felhasználók saját profilképet tölthessenek fel?',
],
'captcha' => [
'enable' => 'Engedélyezés',
'disable' => 'Letiltás',
'info_label' => 'Infó',
'info' => 'A kulcsokat a <u><a href="https://developers.cloudflare.com/turnstile/get-started/#get-a-sitekey-and-secret-key" target="_blank">Cloudflare Vezérlőpultodon</a></u> tudod létrehozni. Ehhez Cloudflare fiók szükséges.',
'site_key' => 'Webhely kulcsa',
'secret_key' => 'Titkos kulcs',
'verify' => 'Domain ellenőrzése?',
],
'mail' => [
'mail_driver' => 'Levelezési driver',
'test_mail' => 'Tesztlevél küldése',
'test_mail_sent' => 'Tesztlevél elküldve',
'test_mail_failed' => 'Tesztlevél küldése sikertelen',
'from_settings' => 'Feladó beállításai',
'from_settings_help' => 'Állítsd be a levelek "Feladó" mezőjében használt címet és nevet.',
'from_address' => 'Feladó címe',
'from_name' => 'Küldő neve',
'smtp' => [
'smtp_title' => 'SMTP beállítások',
'host' => 'Hoszt',
'port' => 'Port',
'username' => 'Felhasználónév',
'password' => 'Jelszó',
'scheme' => 'Séma',
],
'mailgun' => [
'mailgun_title' => 'Mailgun beállítások',
'domain' => 'Domain',
'secret' => 'Titkos kulcs',
'endpoint' => 'Végpont',
],
],
'backup' => [
'backup_driver' => 'Biztonsági mentés driver',
'throttle' => 'Korlátozások',
'throttle_help' => 'Állítsd be, hogy egy időszak alatt hány biztonsági mentés hozható létre. Állítsd az időszakot 0-ra a korlátozás kikapcsolásához.
',
'limit' => 'Korlát',
'period' => 'Időszak',
'seconds' => 'Másodperc',
's3' => [
's3_title' => 'S3 Beállítások',
'default_region' => 'Alap Régió',
'access_key' => 'Hozzáférési kulcs ID',
'secret_key' => 'Titkos hozzáférési kulcs',
'bucket' => 'Bucket',
'endpoint' => 'Végpont',
'use_path_style_endpoint' => 'Útvonal-stílusú végpont használata',
],
],
'oauth' => [
'enable' => 'Engedélyezés',
'enable_schema' => 'Engedélyzés :schema',
'disable' => 'Letiltás',
'client_id' => 'Ügyfél ID',
'client_secret' => 'Ügyfél titkos kulcs',
'redirect' => 'Átirányítási URL',
'web_api_key' => 'Web API kulcs',
'base_url' => 'Alap URL',
'display_name' => 'Megjelenített név',
'auth_url' => 'Autorizációs callback URL',
'create_missing_users' => 'Automatikusan létrehozza a hiányzó felhasználókat?',
'link_missing_users' => 'Automatikusan összekapcsolja a hiányzó felhasználókat?',
],
'misc' => [
'auto_allocation' => [
'title' => 'Automatikus allokáció létrehozás',
'helper' => 'Beállítja, hogy a felhasználók létrehozhatnak-e allokációkat a kliens felületen.',
'question' => 'Engeded, hogy a felhasználók allokációkat hozzanak létre?',
'create_new' => 'Új allokáció létrehozása ha nincs?',
'create_new_help' => 'Ha engedélyezve van, új allokációkat hoz létre. Ha letiltva van, csak a meglévő, még nem kiosztott allokációkból oszt ki. Mindkét opció figyelembe veszi az alábbi porttartományt.',
'start' => 'Kezdő port',
'end' => 'Végport',
],
'mail_notifications' => [
'title' => 'Email értesítések',
'helper' => 'Beállítja, hogy mely email értesítések menjenek ki a felhasználóknak.',
'account_created' => 'Fiók Létrehozva',
'added_to_server' => 'Szerverhez Hozzáadva',
'removed_from_server' => 'Eltávolítva a Szerverről',
'server_installed' => 'Szerver telepítve',
'server_reinstalled' => 'Szerver újratelepítve',
'backup_completed' => 'Biztonsági Mentés Befejezve',
],
'connections' => [
'title' => 'Kapcsolatok',
'helper' => 'Időtúllépések a kéréseknél.',
'request_timeout' => 'Kérés időtúllépése',
'connection_timeout' => 'Kapcsolat időtúllépése',
'seconds' => 'Másodperc',
],
'activity_log' => [
'title' => 'Tevékenységnaplók',
'helper' => 'Beállítja, hogy milyen gyakran törlődjenek a régi naplók, és hogy naplózzuk-e az admin tevékenységeket.',
'prune_age' => 'Törlési határidő',
'days' => 'Napok',
'log_admin' => 'Adminisztrátori aktivitások elrejtése?',
],
'api' => [
'title' => 'API',
'helper' => 'Kéréskorlátot meghatározó időtartam, amely alatt a limit érvényes',
'requests_per_period' => 'Kérések egy Időintervallumban',
'requests' => 'Kérések',
'minutes' => 'Percek',
'period_length' => 'Időintervallum hossza',
'client_title' => 'Kliens API kéréskorlát',
'client_helper' => 'Kéréskorlát felhasználónként érvényes, vagy IP-címenként ha nincs felhasználó',
'application_title' => 'App API kéréskorlát',
'application_helper' => 'Kéréskorlát felhasználónként érvényes, vagy IP-címenként ha nincs felhasználó',
'password_reset_title' => 'Jelszó visszaállítás kéréskorlát',
'password_reset_helper' => 'Kéréskorlát IP-címenként',
'websocket_title' => 'Websocket kéréskorlát',
'websocket_helper' => 'Kéréskorlát szerverenként',
'backup_restore_title' => 'Mentés visszaállítás kéréskorlát',
'backup_restore_helper' => 'Kéréskorlát szerverenként',
'database_create_title' => 'Adatbázis létrehozási kéréskorlát',
'database_create_helper' => 'Kéréskorlát szerverenként',
'subuser_create_title' => 'Al felhasználó létrehozási kéréskorlát',
'subuser_create_helper' => 'Kéréskorlát szerverenként',
'file_pull_title' => 'Fájlletöltési kéréskorlát',
'file_pull_helper' => 'Kéréskorlát szerverenként',
'default_title' => 'Alap kéréskorlát',
'default_helper' => 'Kéréskorlát szerverenként',
],
'server' => [
'title' => 'Szerverek',
'helper' => 'Szerver beállítások',
'edit_server_desc' => 'Engeded, hogy a felhasználók szerkeszthessék a leírásokat?',
'console_font_upload' => 'Konzol betűtípus feltöltés',
'console_font_hint' => 'Csak *.ttf betűtípusok támogatottak. Monospace betűtípus ajánlott!',
],
'webhook' => [
'title' => 'Webhookok',
'helper' => 'Beállítja, hogy milyen gyakran törlődjenek a régi webhook naplók.',
'prune_age' => 'Törlési határidő',
'days' => 'Napok',
],
],
];

View File

@@ -6,17 +6,22 @@ return [
'model_label_plural' => 'Webhookok',
'endpoint' => 'Végpont',
'description' => 'Leírás',
'name' => 'Név',
'type' => 'Tipus',
'server' => 'Szerver',
'information' => 'Információ',
'payload' => 'Terhelés',
'events' => 'Események',
'no_webhooks' => 'Nincs Webhookok',
'help' => 'Súgó',
'help_text' => 'A változó nevét a {{ }}} közé kell tenned, például ha a nevet az api-ból akarod megkapni, használhatod a {{name}} változó.',
'test_now' => 'Tesztelés',
'test_now_help' => 'Ez egy `created: Server` esemény',
'test_now' => 'Tesz most',
'test_now_help' => 'Ez elindítja a `created: Server` eventet',
'table' => [
'description' => 'Leírás',
'endpoint' => 'Végpont',
],
'headers' => 'Fejlécek',
'events' => 'Események',
'regular' => 'Hagyományos',
'reset_headers' => 'Fejlécek visszaállítása',
'discord' => 'Discord',

View File

@@ -20,5 +20,6 @@ return [
'password' => 'A megadott jelszó helytelen.',
'throttle' => 'Túl sok bejelentkezési próbálkozás. Kérlek próbáld újra :seconds másodperc múlva.',
'2fa_must_be_enabled' => 'Az adminisztrátor előírta, hogy a Panel használatához a fiókodhoz kötelező bekapcsolni a kétlépcsős azonosítást.',
'password_login_disabled' => 'Jelszavas belépés le van tiltva. Kérlek használd az OAuth-ot a belépéshez',
];

View File

@@ -60,5 +60,11 @@ return [
],
'server' => [
'marked_as_failed' => 'Ez a szerver még nem fejezte be a telepítési folyamatot, kérlek próbáld újra később.',
'file_too_large' => 'Ez a fájl túl nagy, hogy itt meg tudd nyitni.',
'state_conflict' => 'A szerver jelenleg nem elérhető, próbáld újra később.',
'suspended' => 'Ez a szerver fel van függesztve és ez nem elérhető.',
'maintenance' => 'A node szerver jelenleg karbantartás alatt van így ez nem elérhető.',
'restoring_backup' => 'A szerver jelenleg egy mentést állít vissza, kérlek próbáld újra később.',
'transferring' => 'Ez a szerver jelenleg egy új gépre van migrálva, kérlek próbáld újra később.',
],
];

19
lang/hu/passkeys.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
return [
'authenticate_using_passkey' => 'Belépés passkey használatával',
'create' => 'Létrehozás',
'delete' => 'Törlés',
'error_something_went_wrong_generating_the_passkey' => 'Valami hiba történt a létrehozás során, kérlek próbáld újra később.',
'invalid' => 'Rossz paskey',
'last_used' => 'Utoljára használva',
'name' => 'Név',
'name_placeholder' => 'Az én passkey-em',
'no_passkeys_registered' => 'Nincs egy passkey se regisztrálva',
'not_used_yet' => 'Nincs még használva',
'passkeys' => 'Passkeys',
'description' => 'Jelszó helyett passkey használható, amelyet 1Password, macOS jelszókezelő vagy más alkalmazás tárol a rendszereden.',
'created_notification_title' => 'A te passkey-ed létre lett hozva',
'deleted_notification_title' => 'A passkey-ed ki lett törölve',
'registration_failed_notification_title' => 'Passkey regisztrálás sikertelen',
];

View File

@@ -11,6 +11,7 @@ return [
'keys' => 'Kulcsok',
'2fa' => '2FA',
'customization' => 'Testreszabás',
'passkeys' => 'Passkey',
],
'username' => 'Felhasználónév',
'admin' => 'Adminisztrátor',
@@ -64,7 +65,13 @@ return [
'sidebar' => 'Oldalsáv',
'topbar' => 'Felső sáv',
'mixed' => 'Vegyes',
'button_style' => 'Gomb Stílus',
'icon' => 'Ikon',
'icon_button' => 'Ikon Gomb',
'redirect_to_admin' => 'Bejelentkezéskor átírányitás az admin felületre',
'redirect_to_admin_help' => 'Bekapcsolás után a bejelentkezést követően a szerverlista helyett az admin felületre irányít át.',
'no_oauth' => 'Nincsenek összekapcsolt fiókok',
'no_api_keys' => 'Nincsenek API-kulcsok',
'no_ssh_keys' => 'Nincsenek SSH kulcsok',
'activity_info' => 'Az utolsó 50 aktivitás mutatása',
];

Some files were not shown because too many files have changed in this diff Show More