Files
citrus/public/docs/LOCALIZATION_PATTERN.md
Ümit Tunç 194beaee1c iniit
2025-12-31 21:37:21 +03:00

624 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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ı