# Modül Dil Dosyaları

https://dev.wisecp.com/tr/modul-dil-dosyalari

Modülünüze kendi çevrilebilir metinlerini verin. Dil başına bir dosya, doğrusunun nasıl seçildiği ve eksik bir anahtarın neden İngilizceye düşmediği.

## Genel Bakış

Bir modül metinlerini `lang` dizininde taşır: dil kodu başına bir PHP dosyası, her biri düz bir dizi döndürür. Yükleyici bu dosyalardan tam olarak birini seçer ve dizinin tamamını sınıfınıza bir özellik olarak verir.

Geri düşüş dosya başınadır, anahtar başına değil. Etkin dilin bir dosyası varsa elinizdeki tek şey o dosyadır; tanımlamadığı her anahtar yoktur. Her dosyayı aynı anahtar listesinde tutmak, modeli güvenli kılan şeydir. Burada ölçüldü: bir İngilizce ve bir Türkçe dosya taşıyan 297 modülün 295 çifti birebir aynı üst düzey anahtarlara sahip. Kalan ikisi, İngilizce dosyanın hiç tanımlamadığı anahtarları taşıyan Türkçe dosyalardır; bu makalenin anlattığı arıza budur.

## Ön Koşullar

- Zaten yüklenen bir modül dizini; dil dosyası, sınıflı ya da sınıfsız, her yüklemede okunur.
- Bir İngilizce dosya: kendi dosyası olmayan her dil için son çare.
- Hangi metinlerin sizin, hangilerinin platformun olduğunu bilmek; [Çeviriler ve Dil Dosyaları](https://dev.wisecp.com/tr/ceviriler-ve-dil-dosyalari) makalesinde anlatılıyor.

## Yapı

### Dizin

```bash
coremio/modules/{Type}/{Name}/lang/
├── en.php     # kendi dosyası olmayan her dil için geri düşülen dosya
├── tr.php     # aynı anahtarlar, çevrilmiş
└── de.php     # desteklediğiniz dil başına bir dosya ekleyin; kod, dosya adıdır
```

Her dosya düz bir dizi döndürür. İki anahtarı platform okur; kalanını siz adlandırırsınız.

```php
return [
    // Platformun okuduğu: modül listesindeki etiket ve tanıtım cümlesi.
    'name'        => 'Acme Domains',
    'description' => 'Domain registration through the Acme API. An API key is required.',

    // Sizin. Uzun bir dosyada gezinmek kolay kalsın diye bunları bir önekle gruplayın.
    'username'      => 'Username',
    'username-desc' => 'The API account this installation connects with.',
    'api-key'       => 'API Key',
    'test-mode'     => 'Test Mode',

    'error-no-domain' => 'No domain name is bound to this service.',
    'error-refused'   => 'The provider refused the request.',

    // Yer tutucular konumsaldır ve değerleri çağıran taraf geçer.
    'error-locked' => 'The domain %s is locked and cannot be transferred.',
];
```

### Dosya Nasıl Seçilir

Önce dil çözülür, sonra dosya. İki adım ayrıdır ve yalnız ikincisinin geri düşüşü vardır.

| Sıra | Dili ne belirler | Ne zaman geçerli |
| --- | --- | --- |
| 1 | Geçtiğiniz dil argümanı | Açıkça bir dil adlandırdıysanız |
| 2 | Kayıt defterinin ortak dil işareti | Bu istekte bir modül zaten bir dilde yüklendiyse |
| 3 | Etkin arayüz dili | İşaret hâlâ boşsa |
| 4 | Sistemin varsayılan yereli | Arayüz dili seçilmemişse |
| 5 | İngilizce | Başka hiçbir şey yanıt vermediyse |

```php
// Tam olarak tek bir dosya dahil edilir. İngilizceyle anahtar bazında birleştirme yoktur.
if (file_exists($path . 'lang' . DS . $lang . '.php'))
    $strings = include $path . 'lang' . DS . $lang . '.php';
elseif (file_exists($path . 'lang' . DS . 'en.php'))
    $strings = include $path . 'lang' . DS . 'en.php';

// İkisi de yoksa: özellik boş bir dizidir ve her okuma kendi varsayılanına düşer.
```

## Adım Adım

### Dosyaları Ekleyin

1. `lang/en.php` dosyasını, `name` ve `description` taşıyan bir dizi döndürecek şekilde oluşturun.
2. Onu `lang/tr.php` olarak kopyalayın ve değerleri çevirin; anahtarları olduğu gibi bırakın.
3. Modül listesini yenileyin. Modül artık dizin adı yerine kendi etiketini gösterir.

### Bir Metni Okuyun

1. Sınıfın içinde dil özelliğinden null güvenli bir varsayılanla okuyun. Eski bir çeviriyi çalıştıran bir sistemde anahtar eksik olabilir.
2. İçinde değer geçen bir metinde yer tutucuyu dil dosyasında bırakın. Biçimlendirmeyi çağrı yerinde yapın; böylece çevirmen cümlenin tamamını görür.
3. Panel dilini değiştirip yenileyin. Aynı kod artık diğer dosyanın değerini verir.

### Bir Yapılandırma Girdisini Etiketleyin

1. Bir ayar alanı tanımında dil değerini `name` ve `description` girdilerine koyun. O dizi çalışma anında kurulur ve özelliği okuyabilir.
2. Bir sunucu modülünün yapılandırma dosyasında kod değil durağan veri olan yerlerde `{lang.key}` yer tutucu biçimini yazın. Modül bunu aynı diziye karşı çözer.
3. Ayar ekranını iki dilde de açın ve her etiketin dili izlediğini doğrulayın.

## Referans

### Yükleyici

```php
// Modül metinleri. Dosyayı kendisi yükler, yani önceden bir yükleme çağrısı gerekmez.
// $lang, 'en' ya da 'tr' gibi bir dil kodudur; boş bırakmak "sen çöz" demektir.
public static function Lang($type, $module, $lang = '');

// Modül yapılandırması. YALNIZ statik önbelleği okur: kimse yüklemediyse null döner.
// Lang() ile arasındaki bu asimetri, ikilinin en şaşırtıcı yanıdır.
public static function Config($type, $module);

// Görünen etiket: lang['name'], sonra config['name'], sonra dizin adı.
// Yüklemeyi sizin yerinize yapar.
public static function getName(string $type, string $module): string;

// Platform metinleri, modül metinleri DEĞİL. Modül bunları yalnız ortak ifadeler için kullanır.
public static function g($key = '', $replaces = [], $slang = ''): array|string|int|bool;
public static function gc($name = '', $replaces = [], $slang = ''): array|string|int|bool;
public static function selected(): string;
```

- **Lang()**: Diziyi döndürür; ne istenen dosya ne İngilizce dosya varsa boş dizi. Hiçbir zaman null döndürmez, yani sonucu okumak güvenlidir.
- **Config()**: Modül yüklenmediyse null döndürür, çünkü yalnız önbelleği okur. Dil yükleyicisinin aksine diske gitmez.
- **Ortak dil işareti**: Kayıt defterinin tamamı için tek statik değer; en son istenen dile ayarlanır. Açık bir dil geçmek, sonraki her dilsiz çağrı için onu değiştirir.
- **Ne zaman yeniden yüklenir**: Yalnız istenen dil işaretten farklıysa ya da modülün henüz önbellekte metni yoksa. Önbelleklenmiş bir modül, işaret kaydığında yeniden okunmaz.

### Platformun Okuduğu Anahtarlar

- **name**: Modül listesindeki ve modülün adlandırıldığı her yerdeki etiket. Yoksa: yapılandırmanın ad girdisi, sonra dizin adı.
- **description**: Modül listesinde etiketin altındaki cümle. Operatörün dilinde tek satır: neye bağlanır, neye ihtiyaç duyar.
- **{lang.key}**: Bir sunucu modülünün yapılandırma dosyasında etiket durağan veri olarak durduğunda kabul edilir: kart öğesi, ek parametresi. Modülün kendi dizisine karşı çözülür; bilinmeyen anahtar boş dize yerine yazıldığı gibi görünür.
- **Sıralama yan etkisi**: Bir tip listesi çözülmüş görünen ada göre sıralanır; yani `name` çevirmek modülün o dilde listenin neresinde göründüğünü de değiştirir.

## Örnek

İki dosya, sonra metinlerin okunduğu iki yer: sınıf ve PHP çağıramayan bir yapılandırma girdisi.

```php
// lang/en.php
return [
    'name'            => 'Acme Domains',
    'description'     => 'Domain registration through the Acme API.',
    'api-key'         => 'API Key',
    'api-key-desc'    => 'Found under Account, API in the provider panel.',
    'error-locked'    => 'The domain %s is locked and cannot be transferred.',
    'addon-privacy'   => 'WHOIS Privacy',
];

// lang/tr.php : AYNI anahtarlar, aynı sırada, değerler çevrilmiş.
return [
    'name'            => 'Acme Alan Adları',
    'description'     => 'Acme API üzerinden alan adı kaydı.',
    'api-key'         => 'API Anahtarı',
    'api-key-desc'    => 'Sağlayıcı panelinde Hesap, API altında bulunur.',
    'error-locked'    => '%s alan adı kilitli ve transfer edilemez.',
    'addon-privacy'   => 'WHOIS Gizliliği',
];
```

```php
public function config_fields($data = []): array
{
    return [
        'apiKey' => [
            // Her zaman varsayılanla: bu anahtar var olmadan önce gönderilmiş bir çeviri
            // aksi halde boş bir etiket basardı.
            'name'        => $this->lang['api-key'] ?? 'API Key',
            'description' => $this->lang['api-key-desc'] ?? '',
            'type'        => 'password',
            'value'       => $data['apiKey'] ?? '',
        ],
    ];
}

public function transfer(): array|bool
{
    if ($this->is_locked()) {
        // Yer tutucu dil dosyasında yaşar; değer burada uygulanır,
        // böylece çevirmen iki parça yerine cümlenin tamamını görür.
        $message = sprintf(
            $this->lang['error-locked'] ?? 'The domain %s is locked.',
            (string) ($this->service['domain'] ?? ''),
        );

        throw new \Exception($message);
    }

    // Platform metni, modül metni değil: bu ifade panelin geri kalanıyla paylaşılır
    // ve bu modülün dosyalarına ait değildir.
    if (!$this->credentials()['apiKey'])
        throw new \Exception(\Language::gc("admin/modules/error-missing-credentials"));

    // Başarıda status döndürmeyin: taban sınıf gönderilen transferi inprocess durumuna alır.
    return true;
}
```

```php
return [
    'addon-params' => [
        // Durağan veri; ekran render ederken lang/ dizinine karşı çözülür.
        'whois_privacy' => [
            'label'       => '{lang.addon-privacy}',
            'description' => '{lang.addon-privacy-desc}',
            'type'        => 'toggle',
        ],
    ],
];
```

## Tuzaklar

> **Eksik bir anahtar İngilizceye düşmez**
> 
> İngilizcede olup etkin dilde olmayan bir anahtar yoktur, o kadar. Okumanızın verdiği varsayılan ne ise ekranda o görünür. Bir anahtarı aynı değişiklikte her dil dosyasına ekleyin ve her zaman varsayılanla okuyun.

> **Belirli bir dil istemek ortak bir işareti kaydırır**
> 
> Kayıt defteri istek boyunca tek bir dil işareti tutar ve bir modülü başka bir dilde istemek onu ayarlar. Ölçüldü: işaret kaydıktan sonra önbelleklenmiş bir modül ilk dilini döndürmeye devam etti. Sayfanın tamamı o dilde değilse gösterim yolunda belirli bir dil istemeyin.

> **Modül metinleri ile platform metinleri ayrı sistemlerdir**
> 
> Kendi ifadeleriniz modülün dosyalarında yaşar, dil özelliğinden okunur. Panelle paylaşılan ifadeler platformun çeviri yardımcılarından gelir. Bir modül onlara anahtar ekleyemez; uydurduğunuz her şey kendi dosyanızda durur.

> **Cümleyi parçalardan kurmayın**
> 
> Bir değerin etrafına iki anahtar eklemek, yalnız tek bir dilde işleyen bir kelime sırası üretir. Cümlenin tamamını konumsal yer tutuculu tek bir anahtarda tutun ve değeri çağrı yerinde uygulayın.

> **Yer tutucu biçimi yalnız çözüldüğü yerde çalışır**
> 
> Bir dil yer tutucusunu rastgele bir yapılandırma değerine yazmak hiçbir şey yapmaz. Yalnız çözücünün çağrıldığı yerlerde açılır: sunucu modülünün kart öğesi ve ek parametresi etiketleri. Başka her yerde ekrana düz metin olarak ulaşır.

## İlgili Makaleler

- [Modül Anatomisi](https://dev.wisecp.com/tr/modul-anatomisi)
- [Modül Yapılandırması](https://dev.wisecp.com/tr/modul-yapilandirmasi)
- [Çeviriler ve Dil Dosyaları](https://dev.wisecp.com/tr/ceviriler-ve-dil-dosyalari)
- [Modül Sistemi](https://dev.wisecp.com/tr/modul-sistemi)
- [İlk Modülünüz](https://dev.wisecp.com/tr/ilk-modulunuz)
- [Tema Çevirisi](https://dev.wisecp.com/tr/tema-cevirisi)
