Add localization pattern documentation for Citrus Platform: Created a comprehensive guide detailing the localization structure, translation key organization, and best practices for implementing localization in modules. Included examples for the Pages module to standardize localization efforts across the platform.
This commit is contained in:
@@ -0,0 +1,623 @@
|
||||
# Localization Pattern - Citrus Platform
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Citrus Platform'da tüm modüller Laravel Localization sistemi kullanarak çoklu dil desteği sağlar. Bu dokümantasyon, localization pattern'ini ve Pages modülü örneğini detaylandırır.
|
||||
|
||||
## Pattern Yapısı
|
||||
|
||||
### 1. Dil Dosyası Organizasyonu
|
||||
|
||||
```
|
||||
lang/
|
||||
├── tr/ # Türkçe çeviriler
|
||||
│ ├── pages.php # Pages modülü çevirileri
|
||||
│ ├── users.php # Users modülü çevirileri
|
||||
│ └── common.php # Ortak çeviriler
|
||||
├── en/ # İngilizce çeviriler
|
||||
│ ├── pages.php # Pages modülü çevirileri
|
||||
│ ├── users.php # Users modülü çevirileri
|
||||
│ └── common.php # Ortak çeviriler
|
||||
└── validation.php # Validation mesajları
|
||||
```
|
||||
|
||||
### 2. Çeviri Anahtarı Yapısı
|
||||
|
||||
```php
|
||||
// Modül adı (kebab-case) + alt kategoriler
|
||||
'module_name' => [
|
||||
'title' => 'Modül Başlığı',
|
||||
'navigation_label' => 'Navigasyon Etiketi',
|
||||
'model_label' => 'Tekil Model Etiketi',
|
||||
'plural_model_label' => 'Çoğul Model Etiketi',
|
||||
|
||||
// Actions
|
||||
'create' => 'Oluştur',
|
||||
'edit' => 'Düzenle',
|
||||
'delete' => 'Sil',
|
||||
'restore' => 'Geri Yükle',
|
||||
'force_delete' => 'Kalıcı Olarak Sil',
|
||||
|
||||
// Form fields
|
||||
'field_name' => 'Alan Etiketi',
|
||||
|
||||
// Status options
|
||||
'status_option' => 'Durum Seçeneği',
|
||||
|
||||
// Messages
|
||||
'created_successfully' => 'Başarıyla oluşturuldu.',
|
||||
'updated_successfully' => 'Başarıyla güncellendi.',
|
||||
'deleted_successfully' => 'Başarıyla silindi.',
|
||||
|
||||
// Table columns
|
||||
'table_column_name' => 'Sütun Başlığı',
|
||||
|
||||
// Validation messages
|
||||
'field_required' => 'Bu alan zorunludur.',
|
||||
'field_unique' => 'Bu değer zaten kullanılıyor.',
|
||||
];
|
||||
```
|
||||
|
||||
## Pages Modülü - Örnek Uygulama
|
||||
|
||||
### 1. Resource Sınıfı Localization
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages;
|
||||
|
||||
use Filament\Resources\Resource;
|
||||
|
||||
class PageResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Page::class;
|
||||
|
||||
// Navigation ve model etiketleri için localization
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('pages.navigation_label');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('pages.model_label');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('pages.plural_model_label');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Page Sınıfları Localization
|
||||
|
||||
#### ListPages.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages\Pages;
|
||||
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Actions\CreateAction;
|
||||
|
||||
class ListPages extends ListRecords
|
||||
{
|
||||
protected static string $resource = PageResource::class;
|
||||
|
||||
// Sayfa başlığı için localization
|
||||
public function getTitle(): string
|
||||
{
|
||||
return __('pages.title');
|
||||
}
|
||||
|
||||
// Action butonları için localization
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make()
|
||||
->label(__('pages.create')),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### CreatePage.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages\Pages;
|
||||
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreatePage extends CreateRecord
|
||||
{
|
||||
protected static string $resource = PageResource::class;
|
||||
|
||||
// Sayfa başlığı
|
||||
public function getTitle(): string
|
||||
{
|
||||
return __('pages.create');
|
||||
}
|
||||
|
||||
// Başarı mesajı
|
||||
protected function getCreatedNotificationTitle(): ?string
|
||||
{
|
||||
return __('pages.created_successfully');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### EditPage.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages\Pages;
|
||||
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\ForceDeleteAction;
|
||||
use Filament\Actions\RestoreAction;
|
||||
|
||||
class EditPage extends EditRecord
|
||||
{
|
||||
protected static string $resource = PageResource::class;
|
||||
|
||||
// Sayfa başlığı
|
||||
public function getTitle(): string
|
||||
{
|
||||
return __('pages.edit');
|
||||
}
|
||||
|
||||
// Action butonları
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make()
|
||||
->label(__('pages.delete')),
|
||||
ForceDeleteAction::make()
|
||||
->label(__('pages.force_delete')),
|
||||
RestoreAction::make()
|
||||
->label(__('pages.restore')),
|
||||
];
|
||||
}
|
||||
|
||||
// Başarı mesajı
|
||||
protected function getSavedNotificationTitle(): ?string
|
||||
{
|
||||
return __('pages.updated_successfully');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Form ve Table Localization
|
||||
|
||||
#### PageForm.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages\Schemas;
|
||||
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class PageForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label(__('pages.title_field'))
|
||||
->required()
|
||||
->validationMessages([
|
||||
'required' => __('pages.title_required'),
|
||||
]),
|
||||
|
||||
TextInput::make('slug')
|
||||
->label(__('pages.slug_field'))
|
||||
->required()
|
||||
->validationMessages([
|
||||
'required' => __('pages.slug_required'),
|
||||
'unique' => __('pages.slug_unique'),
|
||||
]),
|
||||
|
||||
Textarea::make('content')
|
||||
->label(__('pages.content_field'))
|
||||
->required()
|
||||
->validationMessages([
|
||||
'required' => __('pages.content_required'),
|
||||
]),
|
||||
|
||||
Select::make('status')
|
||||
->label(__('pages.status_field'))
|
||||
->options([
|
||||
'draft' => __('pages.status_draft'),
|
||||
'published' => __('pages.status_published'),
|
||||
'archived' => __('pages.status_archived'),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### PagesTable.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Admin\Resources\Pages\Tables;
|
||||
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Columns\BadgeColumn;
|
||||
|
||||
class PagesTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('title')
|
||||
->label(__('pages.table_title'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('slug')
|
||||
->label(__('pages.table_slug'))
|
||||
->searchable(),
|
||||
|
||||
BadgeColumn::make('status')
|
||||
->label(__('pages.table_status'))
|
||||
->colors([
|
||||
'warning' => 'draft',
|
||||
'success' => 'published',
|
||||
'danger' => 'archived',
|
||||
]),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('pages.table_created_at'))
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('updated_at')
|
||||
->label(__('pages.table_updated_at'))
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dil Dosyası Örnekleri
|
||||
|
||||
### Türkçe (lang/tr/pages.php)
|
||||
```php
|
||||
<?php
|
||||
|
||||
return [
|
||||
// Genel
|
||||
'title' => 'Sayfalar',
|
||||
'navigation_label' => 'Sayfalar',
|
||||
'model_label' => 'Sayfa',
|
||||
'plural_model_label' => 'Sayfalar',
|
||||
|
||||
// Actions
|
||||
'create' => 'Yeni Sayfa Oluştur',
|
||||
'edit' => 'Sayfayı Düzenle',
|
||||
'delete' => 'Sayfayı Sil',
|
||||
'restore' => 'Sayfayı Geri Yükle',
|
||||
'force_delete' => 'Kalıcı Olarak Sil',
|
||||
|
||||
// Form fields
|
||||
'title_field' => 'Başlık',
|
||||
'slug_field' => 'URL Yolu',
|
||||
'content_field' => 'İçerik',
|
||||
'meta_title_field' => 'Meta Başlık',
|
||||
'meta_description_field' => 'Meta Açıklama',
|
||||
'status_field' => 'Durum',
|
||||
'published_at_field' => 'Yayın Tarihi',
|
||||
|
||||
// Status options
|
||||
'status_draft' => 'Taslak',
|
||||
'status_published' => 'Yayınlandı',
|
||||
'status_archived' => 'Arşivlendi',
|
||||
|
||||
// Messages
|
||||
'created_successfully' => 'Sayfa başarıyla oluşturuldu.',
|
||||
'updated_successfully' => 'Sayfa başarıyla güncellendi.',
|
||||
'deleted_successfully' => 'Sayfa başarıyla silindi.',
|
||||
'restored_successfully' => 'Sayfa başarıyla geri yüklendi.',
|
||||
|
||||
// Table columns
|
||||
'table_title' => 'Başlık',
|
||||
'table_slug' => 'URL Yolu',
|
||||
'table_status' => 'Durum',
|
||||
'table_created_at' => 'Oluşturulma Tarihi',
|
||||
'table_updated_at' => 'Güncellenme Tarihi',
|
||||
|
||||
// Validation messages
|
||||
'title_required' => 'Başlık alanı zorunludur.',
|
||||
'slug_required' => 'URL yolu alanı zorunludur.',
|
||||
'slug_unique' => 'Bu URL yolu zaten kullanılıyor.',
|
||||
'content_required' => 'İçerik alanı zorunludur.',
|
||||
];
|
||||
```
|
||||
|
||||
### İngilizce (lang/en/pages.php)
|
||||
```php
|
||||
<?php
|
||||
|
||||
return [
|
||||
// General
|
||||
'title' => 'Pages',
|
||||
'navigation_label' => 'Pages',
|
||||
'model_label' => 'Page',
|
||||
'plural_model_label' => 'Pages',
|
||||
|
||||
// Actions
|
||||
'create' => 'Create New Page',
|
||||
'edit' => 'Edit Page',
|
||||
'delete' => 'Delete Page',
|
||||
'restore' => 'Restore Page',
|
||||
'force_delete' => 'Force Delete',
|
||||
|
||||
// Form fields
|
||||
'title_field' => 'Title',
|
||||
'slug_field' => 'URL Slug',
|
||||
'content_field' => 'Content',
|
||||
'meta_title_field' => 'Meta Title',
|
||||
'meta_description_field' => 'Meta Description',
|
||||
'status_field' => 'Status',
|
||||
'published_at_field' => 'Published At',
|
||||
|
||||
// Status options
|
||||
'status_draft' => 'Draft',
|
||||
'status_published' => 'Published',
|
||||
'status_archived' => 'Archived',
|
||||
|
||||
// Messages
|
||||
'created_successfully' => 'Page created successfully.',
|
||||
'updated_successfully' => 'Page updated successfully.',
|
||||
'deleted_successfully' => 'Page deleted successfully.',
|
||||
'restored_successfully' => 'Page restored successfully.',
|
||||
|
||||
// Table columns
|
||||
'table_title' => 'Title',
|
||||
'table_slug' => 'URL Slug',
|
||||
'table_status' => 'Status',
|
||||
'table_created_at' => 'Created At',
|
||||
'table_updated_at' => 'Updated At',
|
||||
|
||||
// Validation messages
|
||||
'title_required' => 'The title field is required.',
|
||||
'slug_required' => 'The URL slug field is required.',
|
||||
'slug_unique' => 'This URL slug is already taken.',
|
||||
'content_required' => 'The content field is required.',
|
||||
];
|
||||
```
|
||||
|
||||
## Kullanım Örnekleri
|
||||
|
||||
### 1. Blade Template'lerde
|
||||
```blade
|
||||
<!-- Sayfa başlığı -->
|
||||
<h1>{{ __('pages.title') }}</h1>
|
||||
|
||||
<!-- Buton -->
|
||||
<button>{{ __('pages.create') }}</button>
|
||||
|
||||
<!-- Durum -->
|
||||
<span class="status">{{ __('pages.status_published') }}</span>
|
||||
|
||||
<!-- Form alanı -->
|
||||
<label>{{ __('pages.title_field') }}</label>
|
||||
```
|
||||
|
||||
### 2. Controller'larda
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$title = __('pages.title');
|
||||
$pages = Page::all();
|
||||
|
||||
return view('pages.index', compact('title', 'pages'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$page = Page::create($request->validated());
|
||||
|
||||
return redirect()->route('pages.index')
|
||||
->with('success', __('pages.created_successfully'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. JavaScript'te
|
||||
```javascript
|
||||
// Alpine.js component'inde
|
||||
Alpine.data('pageForm', () => ({
|
||||
title: '',
|
||||
content: '',
|
||||
|
||||
submit() {
|
||||
// Form submission logic
|
||||
this.$dispatch('notify', {
|
||||
type: 'success',
|
||||
message: this.$t('pages.created_successfully')
|
||||
});
|
||||
}
|
||||
}));
|
||||
```
|
||||
|
||||
## Dil Değiştirme
|
||||
|
||||
### 1. Runtime'da Dil Değiştirme
|
||||
```php
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
// Türkçe'ye geç
|
||||
App::setLocale('tr');
|
||||
|
||||
// İngilizce'ye geç
|
||||
App::setLocale('en');
|
||||
|
||||
// Mevcut dili al
|
||||
$currentLocale = App::getLocale();
|
||||
```
|
||||
|
||||
### 2. Route ile Dil Değiştirme
|
||||
```php
|
||||
// routes/web.php
|
||||
Route::get('/lang/{locale}', function ($locale) {
|
||||
if (in_array($locale, ['tr', 'en'])) {
|
||||
App::setLocale($locale);
|
||||
session(['locale' => $locale]);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Middleware ile Dil Yönetimi
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class SetLocale
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$locale = $request->session()->get('locale', config('app.locale'));
|
||||
App::setLocale($locale);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Çeviri Anahtarı Adlandırma
|
||||
- ✅ `pages.create` - Modül.action
|
||||
- ✅ `pages.title_field` - Modül.field_type
|
||||
- ✅ `pages.status_published` - Modül.status_value
|
||||
- ❌ `create_page` - Açıklayıcı değil
|
||||
- ❌ `pageTitle` - camelCase kullanma
|
||||
|
||||
### 2. Çeviri Dosyası Organizasyonu
|
||||
- ✅ Her modül için ayrı dosya
|
||||
- ✅ Ortak çeviriler için `common.php`
|
||||
- ✅ Validation mesajları için `validation.php`
|
||||
- ❌ Tüm çevirileri tek dosyada toplama
|
||||
|
||||
### 3. Çeviri Kalitesi
|
||||
- ✅ Kısa ve açıklayıcı
|
||||
- ✅ Tutarlı terminoloji
|
||||
- ✅ Kültürel uygunluk
|
||||
- ❌ Kelime kelime çeviri
|
||||
- ❌ Teknik jargon
|
||||
|
||||
### 4. Performans
|
||||
- ✅ Çevirileri cache'le
|
||||
- ✅ Lazy loading kullan
|
||||
- ❌ Her request'te dosya okuma
|
||||
- ❌ Gereksiz çeviri yükleme
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
### 1. Localization Test'leri
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Localization;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
class PagesLocalizationTest extends TestCase
|
||||
{
|
||||
public function test_turkish_translations_exist()
|
||||
{
|
||||
app()->setLocale('tr');
|
||||
|
||||
$this->assertNotEmpty(__('pages.title'));
|
||||
$this->assertNotEmpty(__('pages.create'));
|
||||
$this->assertNotEmpty(__('pages.edit'));
|
||||
}
|
||||
|
||||
public function test_english_translations_exist()
|
||||
{
|
||||
app()->setLocale('en');
|
||||
|
||||
$this->assertNotEmpty(__('pages.title'));
|
||||
$this->assertNotEmpty(__('pages.create'));
|
||||
$this->assertNotEmpty(__('pages.edit'));
|
||||
}
|
||||
|
||||
public function test_fallback_locale_works()
|
||||
{
|
||||
app()->setLocale('fr'); // Desteklenmeyen dil
|
||||
|
||||
// Fallback locale'e düşmeli
|
||||
$this->assertEquals('Pages', __('pages.title'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. UI Test'leri
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Admin\Pages;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
class PagesUITest extends TestCase
|
||||
{
|
||||
public function test_pages_list_shows_turkish_labels()
|
||||
{
|
||||
app()->setLocale('tr');
|
||||
|
||||
$response = $this->get(route('filament.admin.resources.pages.index'));
|
||||
|
||||
$response->assertSee('Sayfalar');
|
||||
$response->assertSee('Yeni Sayfa Oluştur');
|
||||
}
|
||||
|
||||
public function test_pages_list_shows_english_labels()
|
||||
{
|
||||
app()->setLocale('en');
|
||||
|
||||
$response = $this->get(route('filament.admin.resources.pages.index'));
|
||||
|
||||
$response->assertSee('Pages');
|
||||
$response->assertSee('Create New Page');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Sonuç
|
||||
|
||||
Bu localization pattern'i, Citrus Platform'da tutarlı ve ölçeklenebilir çoklu dil desteği sağlar. Pages modülü, bu pattern'in uygulandığı örnek modüldür ve tüm yeni modüller için referans alınmalıdır.
|
||||
|
||||
### Önemli Noktalar:
|
||||
1. **Tutarlılık**: Tüm modüller aynı pattern'i kullanmalı
|
||||
2. **Kapsamlılık**: Tüm UI elementleri için çeviri sağlanmalı
|
||||
3. **Test Edilebilirlik**: Localization test'leri yazılmalı
|
||||
4. **Performans**: Çeviriler cache'lenmeli
|
||||
5. **Bakım Kolaylığı**: Çeviri dosyaları düzenli tutulmalı
|
||||
Reference in New Issue
Block a user