Implement Localization for Product and ProductCategory Resources: Refactored resource classes and forms to utilize Laravel's localization features, enhancing user experience by providing translated labels and sections. Added English and Turkish language support for product and category management, ensuring consistency across the admin panel.
This commit is contained in:
@@ -20,21 +20,24 @@ class ProductCategoryResource extends Resource
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedTag;
|
||||
|
||||
protected static \UnitEnum|string|null $navigationGroup = 'Ürün ve Hizmetler';
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('product_categories.navigation_group');
|
||||
}
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return 'Kategoriler';
|
||||
return __('product_categories.menu_label');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return 'Kategori';
|
||||
return __('product_categories.model_label');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return 'Kategoriler';
|
||||
return __('product_categories.plural_model_label');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
|
||||
@@ -16,13 +16,14 @@ class ProductCategoryForm
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
Section::make('General')
|
||||
Section::make(__('product_categories.general_section'))
|
||||
->schema([
|
||||
TextInput::make('slug')
|
||||
->label(__('product_categories.slug'))
|
||||
->required()
|
||||
->unique(ignoreRecord: true),
|
||||
Select::make('parent_id')
|
||||
->label('Parent Category')
|
||||
->label(__('product_categories.parent_category'))
|
||||
->options(function () {
|
||||
return ProductCategory::all()->mapWithKeys(function ($category) {
|
||||
$title = is_array($category->title)
|
||||
@@ -33,18 +34,20 @@ class ProductCategoryForm
|
||||
})
|
||||
->searchable(),
|
||||
TextInput::make('sort_order')
|
||||
->label(__('product_categories.sort_order'))
|
||||
->numeric()
|
||||
->default(0),
|
||||
Toggle::make('is_active')
|
||||
->label(__('product_categories.is_active'))
|
||||
->default(true),
|
||||
])->columns(2),
|
||||
|
||||
Section::make('Translations')
|
||||
Section::make(__('product_categories.translations_section'))
|
||||
->schema([
|
||||
TranslationTabs::make([
|
||||
'title' => [
|
||||
'type' => 'text',
|
||||
'label' => 'Title',
|
||||
'label' => __('product_categories.title'),
|
||||
'required' => true,
|
||||
],
|
||||
]),
|
||||
|
||||
@@ -17,18 +17,23 @@ class ProductCategoriesTable
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('title')
|
||||
->label(__('product_categories.title'))
|
||||
->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state)
|
||||
->searchable()
|
||||
->sortable(),
|
||||
TextColumn::make('slug')
|
||||
->label(__('product_categories.slug'))
|
||||
->searchable(),
|
||||
TextColumn::make('parent.title') // This might fail if parent title is JSON
|
||||
->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state)
|
||||
->label('Parent'),
|
||||
->label(__('product_categories.parent')),
|
||||
TextColumn::make('sort_order')
|
||||
->label(__('product_categories.sort_order'))
|
||||
->sortable(),
|
||||
ToggleColumn::make('is_active'),
|
||||
ToggleColumn::make('is_active')
|
||||
->label(__('product_categories.is_active')),
|
||||
TextColumn::make('created_at')
|
||||
->label(__('product_categories.created_at'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
@@ -20,21 +20,24 @@ class ProductResource extends Resource
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCube;
|
||||
|
||||
protected static \UnitEnum|string|null $navigationGroup = 'Ürün ve Hizmetler';
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('products.navigation_group');
|
||||
}
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return 'Ürün ve Hizmet Listesi';
|
||||
return __('products.menu_label');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return 'Ürün/Hizmet';
|
||||
return __('products.model_label');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return 'Ürün ve Hizmetler';
|
||||
return __('products.plural_model_label');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
|
||||
@@ -17,19 +17,21 @@ class ProductForm
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
Section::make('General')
|
||||
Section::make(__('products.general_section'))
|
||||
->schema([
|
||||
TextInput::make('slug')
|
||||
->label(__('products.slug'))
|
||||
->required()
|
||||
->unique(ignoreRecord: true),
|
||||
Select::make('type')
|
||||
->label(__('products.type'))
|
||||
->options([
|
||||
'product' => 'Product',
|
||||
'service' => 'Service',
|
||||
'product' => __('products.product'),
|
||||
'service' => __('products.service'),
|
||||
])
|
||||
->required(),
|
||||
Select::make('product_category_id')
|
||||
->label('Category')
|
||||
->label(__('products.category'))
|
||||
->options(function () {
|
||||
return ProductCategory::all()->mapWithKeys(function ($category) {
|
||||
$title = is_array($category->title)
|
||||
@@ -40,30 +42,33 @@ class ProductForm
|
||||
})
|
||||
->searchable(),
|
||||
FileUpload::make('hero_image')
|
||||
->label(__('products.hero_image'))
|
||||
->image()
|
||||
->directory('products'),
|
||||
TextInput::make('view_template')
|
||||
->label('Custom View Path')
|
||||
->placeholder('e.g. front.products.custom-page')
|
||||
->helperText('Leave empty to use the default landing page.'),
|
||||
->label(__('products.view_template'))
|
||||
->placeholder(__('products.view_template_placeholder'))
|
||||
->helperText(__('products.view_template_helper')),
|
||||
TextInput::make('sort_order')
|
||||
->label(__('products.sort_order'))
|
||||
->numeric()
|
||||
->default(0),
|
||||
Toggle::make('is_active')
|
||||
->label(__('products.is_active'))
|
||||
->default(true),
|
||||
])->columns(2),
|
||||
|
||||
Section::make('Translations')
|
||||
Section::make(__('products.translations_section'))
|
||||
->schema([
|
||||
TranslationTabs::make([
|
||||
'title' => [
|
||||
'type' => 'text',
|
||||
'label' => 'Title',
|
||||
'label' => __('products.title'),
|
||||
'required' => true,
|
||||
],
|
||||
'content' => [
|
||||
'type' => 'richtext',
|
||||
'label' => 'Content',
|
||||
'label' => __('products.content'),
|
||||
],
|
||||
]),
|
||||
]),
|
||||
|
||||
@@ -17,23 +17,33 @@ class ProductsTable
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
ImageColumn::make('hero_image'),
|
||||
ImageColumn::make('hero_image')
|
||||
->label(__('products.hero_image')),
|
||||
TextColumn::make('title')
|
||||
->label(__('products.title'))
|
||||
->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state)
|
||||
->searchable()
|
||||
->sortable(),
|
||||
TextColumn::make('type')
|
||||
->label(__('products.type'))
|
||||
->badge()
|
||||
->color(fn (string $state): string => match ($state) {
|
||||
'product' => 'info',
|
||||
'service' => 'success',
|
||||
default => 'gray',
|
||||
})
|
||||
->formatStateUsing(fn (string $state): string => match ($state) {
|
||||
'product' => __('products.product'),
|
||||
'service' => __('products.service'),
|
||||
default => $state,
|
||||
}),
|
||||
TextColumn::make('category.title')
|
||||
->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state)
|
||||
->label('Category'),
|
||||
ToggleColumn::make('is_active'),
|
||||
->label(__('products.category')),
|
||||
ToggleColumn::make('is_active')
|
||||
->label(__('products.is_active')),
|
||||
TextColumn::make('sort_order')
|
||||
->label(__('products.sort_order'))
|
||||
->sortable(),
|
||||
])
|
||||
->filters([
|
||||
|
||||
@@ -22,6 +22,7 @@ use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use Filament\Navigation\MenuItem;
|
||||
use App\Models\Language;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Http\Middleware\SetLocale;
|
||||
|
||||
class AdminPanelProvider extends PanelProvider
|
||||
{
|
||||
@@ -67,6 +68,7 @@ class AdminPanelProvider extends PanelProvider
|
||||
SubstituteBindings::class,
|
||||
DisableBladeIconComponents::class,
|
||||
DispatchServingFilamentEvent::class,
|
||||
SetLocale::class,
|
||||
])
|
||||
->authMiddleware([
|
||||
Authenticate::class,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'navigation_group' => 'Products & Services',
|
||||
'menu_label' => 'Categories',
|
||||
'model_label' => 'Category',
|
||||
'plural_model_label' => 'Categories',
|
||||
|
||||
// Form
|
||||
'general_section' => 'General Information',
|
||||
'slug' => 'Slug',
|
||||
'parent_category' => 'Parent Category',
|
||||
'sort_order' => 'Sort Order',
|
||||
'is_active' => 'Active',
|
||||
'translations_section' => 'Translations',
|
||||
|
||||
// Table
|
||||
'title' => 'Title',
|
||||
'parent' => 'Parent Category',
|
||||
'created_at' => 'Created At',
|
||||
];
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'navigation_group' => 'Products & Services',
|
||||
'menu_label' => 'Product & Service List',
|
||||
'model_label' => 'Product/Service',
|
||||
'plural_model_label' => 'Products & Services',
|
||||
|
||||
// Form
|
||||
'general_section' => 'General Information',
|
||||
'slug' => 'Slug',
|
||||
'type' => 'Type',
|
||||
'product' => 'Product',
|
||||
'service' => 'Service',
|
||||
'category' => 'Category',
|
||||
'hero_image' => 'Hero Image',
|
||||
'view_template' => 'Custom View Path',
|
||||
'view_template_placeholder' => 'e.g. front.products.custom-page',
|
||||
'view_template_helper' => 'Leave empty to use the default landing page.',
|
||||
'sort_order' => 'Sort Order',
|
||||
'is_active' => 'Active',
|
||||
'translations_section' => 'Translations',
|
||||
'content' => 'Content',
|
||||
|
||||
// Table
|
||||
'title' => 'Title',
|
||||
'created_at' => 'Created At',
|
||||
];
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'navigation_group' => 'Ürün ve Hizmetler',
|
||||
'menu_label' => 'Kategoriler',
|
||||
'model_label' => 'Kategori',
|
||||
'plural_model_label' => 'Kategoriler',
|
||||
|
||||
// Form
|
||||
'general_section' => 'Genel Bilgiler',
|
||||
'slug' => 'Slug (Bağlantı Yolu)',
|
||||
'parent_category' => 'Üst Kategori',
|
||||
'sort_order' => 'Sıralama',
|
||||
'is_active' => 'Aktif',
|
||||
'translations_section' => 'Çeviriler',
|
||||
|
||||
// Table
|
||||
'title' => 'Başlık',
|
||||
'parent' => 'Üst Kategori',
|
||||
'created_at' => 'Oluşturulma Tarihi',
|
||||
];
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'navigation_group' => 'Ürün ve Hizmetler',
|
||||
'menu_label' => 'Ürün ve Hizmet Listesi',
|
||||
'model_label' => 'Ürün/Hizmet',
|
||||
'plural_model_label' => 'Ürün ve Hizmetler',
|
||||
|
||||
// Form
|
||||
'general_section' => 'Genel Bilgiler',
|
||||
'slug' => 'Slug (Bağlantı Yolu)',
|
||||
'type' => 'Tür',
|
||||
'product' => 'Ürün',
|
||||
'service' => 'Hizmet',
|
||||
'category' => 'Kategori',
|
||||
'hero_image' => 'Kapak Görseli',
|
||||
'view_template' => 'Özel Görünüm Yolu',
|
||||
'view_template_placeholder' => 'örn: front.products.ozel-sayfa',
|
||||
'view_template_helper' => 'Varsayılan şablonu kullanmak için boş bırakın.',
|
||||
'sort_order' => 'Sıralama',
|
||||
'is_active' => 'Aktif',
|
||||
'translations_section' => 'Çeviriler',
|
||||
'content' => 'İçerik',
|
||||
|
||||
// Table
|
||||
'title' => 'Başlık',
|
||||
'created_at' => 'Oluşturulma Tarihi',
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user