Add Language Management Module: Created Language resource with CRUD pages, schemas, and models to support the universal translation system. Implemented localization for English and Turkish, ensuring consistent user experience. Added necessary policies and seeder for initial language data, enhancing the overall language management functionality.

This commit is contained in:
Ümit Tunç
2025-10-01 04:15:21 -03:00
parent 7cbbf521e1
commit a4aea280f2
21 changed files with 2398 additions and 4 deletions
@@ -0,0 +1,68 @@
<?php
namespace App\Filament\Admin\Resources\Languages;
use App\Filament\Admin\Resources\Languages\Pages\CreateLanguage;
use App\Filament\Admin\Resources\Languages\Pages\EditLanguage;
use App\Filament\Admin\Resources\Languages\Pages\ListLanguages;
use App\Models\Language;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
class LanguageResource extends Resource
{
protected static ?string $model = Language::class;
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedGlobeAlt;
protected static UnitEnum|string|null $navigationGroup = 'System';
protected static ?int $navigationSort = 100;
public static function getNavigationLabel(): string
{
return __('language.navigation_label');
}
public static function getModelLabel(): string
{
return __('language.model_label');
}
public static function getPluralModelLabel(): string
{
return __('language.plural_model_label');
}
public static function form(Schema $schema): Schema
{
return $schema
->schema(\App\Filament\Admin\Resources\Languages\Schemas\LanguageForm::schema());
}
public static function table(Table $table): Table
{
return \App\Filament\Admin\Resources\Languages\Tables\LanguagesTable::configure($table);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => ListLanguages::route('/'),
'create' => CreateLanguage::route('/create'),
'edit' => EditLanguage::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Filament\Admin\Resources\Languages\Pages;
use App\Filament\Admin\Resources\Languages\LanguageResource;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
class CreateLanguage extends CreateRecord
{
protected static string $resource = LanguageResource::class;
public function getTitle(): string
{
return __('language.create');
}
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title(__('language.created_successfully'))
->body(__('language.created_successfully_body'));
}
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['created_by'] = auth()->id();
$data['updated_by'] = auth()->id();
return $data;
}
}
@@ -0,0 +1,53 @@
<?php
namespace App\Filament\Admin\Resources\Languages\Pages;
use App\Filament\Admin\Resources\Languages\LanguageResource;
use Filament\Actions\DeleteAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\RestoreAction;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
class EditLanguage extends EditRecord
{
protected static string $resource = LanguageResource::class;
public function getTitle(): string
{
return __('language.edit');
}
protected function getHeaderActions(): array
{
return [
DeleteAction::make()
->label(__('language.delete')),
RestoreAction::make()
->label(__('language.restore')),
ForceDeleteAction::make()
->label(__('language.force_delete')),
];
}
protected function getSavedNotification(): ?Notification
{
return Notification::make()
->success()
->title(__('language.updated_successfully'))
->body(__('language.updated_successfully_body'));
}
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
protected function mutateFormDataBeforeSave(array $data): array
{
$data['updated_by'] = auth()->id();
return $data;
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Filament\Admin\Resources\Languages\Pages;
use App\Filament\Admin\Resources\Languages\LanguageResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
class ListLanguages extends ListRecords
{
protected static string $resource = LanguageResource::class;
public function getTitle(): string
{
return __('language.title');
}
protected function getHeaderActions(): array
{
return [
CreateAction::make()
->label(__('language.create')),
];
}
}
@@ -0,0 +1,95 @@
<?php
namespace App\Filament\Admin\Resources\Languages\Schemas;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Section;
use Illuminate\Support\Str;
class LanguageForm
{
public static function schema(): array
{
return [
Section::make(__('language.basic_information'))
->schema([
Grid::make(2)->schema([
TextInput::make('code')
->label(__('language.code'))
->required()
->unique(ignoreRecord: true)
->maxLength(10)
->placeholder('tr, en, de')
->helperText(__('language.code_helper'))
->columnSpan(1),
TextInput::make('flag')
->label(__('language.flag'))
->maxLength(10)
->placeholder('🇹🇷')
->helperText(__('language.flag_helper'))
->columnSpan(1),
]),
Grid::make(2)->schema([
TextInput::make('name')
->label(__('language.name'))
->required()
->maxLength(100)
->placeholder('Turkish')
->helperText(__('language.name_helper'))
->columnSpan(1),
TextInput::make('native_name')
->label(__('language.native_name'))
->required()
->maxLength(100)
->placeholder('Türkçe')
->helperText(__('language.native_name_helper'))
->columnSpan(1),
]),
Grid::make(2)->schema([
Select::make('direction')
->label(__('language.direction'))
->options([
'ltr' => __('language.direction_ltr'),
'rtl' => __('language.direction_rtl'),
])
->default('ltr')
->required()
->columnSpan(1),
TextInput::make('sort_order')
->label(__('language.sort_order'))
->numeric()
->default(0)
->helperText(__('language.sort_order_helper'))
->columnSpan(1),
]),
]),
Section::make(__('language.settings'))
->schema([
Grid::make(3)->schema([
Checkbox::make('is_active')
->label(__('language.is_active'))
->default(true)
->helperText(__('language.is_active_helper'))
->columnSpan(1),
Checkbox::make('is_default')
->label(__('language.is_default'))
->default(false)
->helperText(__('language.is_default_helper'))
->columnSpan(1)
->disabled(fn ($record) => $record && $record->is_default),
]),
]),
];
}
}
@@ -0,0 +1,113 @@
<?php
namespace App\Filament\Admin\Resources\Languages\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreAction;
use Filament\Actions\RestoreBulkAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class LanguagesTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
TextColumn::make('flag')
->label(__('language.table_flag'))
->sortable()
->searchable()
->formatStateUsing(fn (?string $state): string =>
'<span style="font-size: 2rem; line-height: 1;">' . ($state ?? '🌐') . '</span>'
)
->html()
->alignCenter(),
TextColumn::make('code')
->label(__('language.table_code'))
->sortable()
->searchable()
->badge()
->color('info'),
TextColumn::make('name')
->label(__('language.table_name'))
->sortable()
->searchable()
->description(fn ($record) => $record->native_name),
IconColumn::make('is_active')
->label(__('language.table_is_active'))
->boolean()
->sortable(),
IconColumn::make('is_default')
->label(__('language.table_is_default'))
->boolean()
->sortable(),
TextColumn::make('direction')
->label(__('language.table_direction'))
->badge()
->color(fn (string $state): string => match ($state) {
'ltr' => 'success',
'rtl' => 'warning',
})
->sortable(),
TextColumn::make('sort_order')
->label(__('language.table_sort_order'))
->numeric()
->sortable(),
TextColumn::make('created_at')
->label(__('language.table_created_at'))
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->label(__('language.table_updated_at'))
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('deleted_at')
->label(__('language.table_deleted_at'))
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
TrashedFilter::make(),
])
->recordActions([
EditAction::make(),
DeleteAction::make(),
RestoreAction::make(),
ForceDeleteAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
ForceDeleteBulkAction::make(),
RestoreBulkAction::make(),
]),
])
->defaultSort('sort_order')
->modifyQueryUsing(fn (Builder $query) => $query->withoutGlobalScopes([
SoftDeletingScope::class,
]));
}
}