Çoklu Dil (i18n) ✓ Canlı

Eklentinin mağazada görünen adı/açıklaması ve manifest içindeki tüm kullanıcıya görünen metinler dil haritasıdır: { "tr": "…", "en": "…" }. Restomenum, tenant'ın panel diline göre doğru çeviriyi seçer; o dilde çeviri yoksa tanımlı bir fallback zincirine düşer.

Çevirileri bugünden girebilirsin. Portal editörü ve MCP araçları çok dilli ad/açıklamayı kaydediyor; marketplace kartının tenant diline göre gösterimi panel güncellemesiyle yakında devreye girer. O ana kadar mağazada taban dil (tr) metni görünür — yani çeviri eklemek hiçbir şeyi bozmaz, yalnızca hazır olursun.

Desteklenen diller

KodDilRol
trTürkçeTaban dil — zorunlu, fallback zincirinin ikinci halkası
enEnglishOpsiyonel çeviri
deDeutschOpsiyonel çeviri
ruРусскийOpsiyonel çeviri

Kodlar BCP-47 / ISO 639-1 küçük harftir ve panelin dil kodu uzayıyla birebir aynıdır. Listede olmayan bir anahtar (örn. fr) sessizce düşürülür — kayıt reddedilmez, o anahtar saklanmaz. Panel bu dördü dışında bir dilde açıksa metin kırılmaz; aşağıdaki fallback zinciri devreye girer.

Fallback zinciri

Bir dil haritasından gösterilecek metin her yerde aynı sırayla seçilir (panel, portal, çalışma zamanı ve veritabanı aynı zinciri uygular):

  1. İstenen dil dolu mu? → map[locale]
  2. Taban dil dolu mu? → map["tr"]
  3. Yukarıdaki tablo sırasında (tr, en, de, ru) ilk dolu değer — deterministiktir, JSON anahtar sırasına bağlı değildir
  4. Hiçbiri yoksa → boş metin ("")
Boş string ≠ çeviri var. { "en": "" } "İngilizce çevirisi yok" demektir; zincir bir sonraki halkaya düşer. Değerler trim'lenerek saklanır ve trim'li döner — baştaki/sondaki boşluklar anlam taşımaz.

SDK aynı zinciri resolveLocalized() ile hazır verir (@restomenum/plugin-sdk):

resolveLocalized — fallback zinciri
import { resolveLocalized } from '@restomenum/plugin-sdk';

const title = { tr: 'Kurye Entegrasyonu', en: 'Courier Integration' };

resolveLocalized(title, 'en');             // 'Courier Integration'
resolveLocalized(title, 'de');             // 'Kurye Entegrasyonu'  ← tr'ye düşer (de çevirisi yok)
resolveLocalized(title, 'fr');             // 'Kurye Entegrasyonu'  ← desteklenmeyen dil de tr'ye düşer
resolveLocalized({ en: 'Only EN' }, 'de'); // 'Only EN'             ← tr yoksa LOCALES sırasındaki ilk dolu

Kendi Custom UI sayfanda kullanıcının dilini App Bridge getContext verir:

iframe — kullanıcının dili
// iframe Custom UI: kullanıcının dilini App Bridge getContext verir
// → { serverId, pluginId, locale, refId }
const ctx = await bridge('getContext');
const label = resolveLocalized(page.title, ctx.locale);

Mağaza listelemesi — ad & açıklama

Marketplace kartındaki ad ve açıklama dil dil girilir. Bu alanlar eklentinin kendisine aittir (manifest'e değil, sürüme iliştirilen mağaza bilgisi önerisi olarak gider) ve sürüm onaylanıp yayınlanınca marketplace'e uygulanır — anında değişmez (Versiyonlama).

mağaza bilgisi önerisi — dil dil
{
  "display_name_i18n": {
    "tr": "Kurye Entegrasyonu",
    "en": "Courier Integration",
    "de": "Kurier-Integration"
  },
  "description_i18n": {
    "tr": "Paketleri kuryeye otomatik aktarır.",
    "en": "Automatically dispatches packets to your courier."
  }
}
AlanTipZorunluAçıklama
display_name_i18nobject<dil, string>✓Eklenti adı. Her dil değeri 3–60 karakter. Taban dil tr zorunlu.
description_i18nobject<dil, string>–Marketplace kartı açıklaması. Her dil değeri en fazla 280 karakter. Tamamen boş bırakılabilir.
Uzunluk kuralı her dil için AYRI AYRI uygulanır. Türkçe adın 60 karaktere sığması, Almanca çevirinin de sığacağı anlamına gelmez — Almanca değer 60 karakteri aşarsa kayıt hata döner (sessizce kırpılmaz). Uzun dillerde metni kısaltmayı baştan planla.
Taban dil tr zorunludur. Dolu bir dil haritasında tr değeri yoksa kayıt reddedilir. Sebep: platformun tek dilli (legacy) ad/açıklama alanı bu haritanın tr çözümüdür ve boş olamaz. Önce tr'yi doldur, çevirileri üstüne ekle.

Manifest metinleri de aynı konvansiyon

Çoklu dil yeni bir mekanizma değildir — manifest'te zaten kullanılıyor. Aynı dil haritası şekli şu alanlarda geçerlidir:

manifest — nav label + page title
"nav": [
  {
    "slot": "sidebar.main",
    "pageId": "dashboard",
    "label": { "tr": "Kurye Paneli", "en": "Courier Panel" }
  }
],
"pages": [
  {
    "id": "dashboard",
    "title": { "tr": "Kurye Paneli", "en": "Courier Panel" },
    "customUiOrigin": "https://acme.example.com"
  }
]
Manifest metinlerinde de aynı fallback zinciri geçerlidir; taban dili doldurmak en güvenli davranıştır. İki fark var: (1) manifest etiketlerinde taban dil zorunlu değildir — en az bir dil yeterli, gerisi zincirle çözülür (buton etiketi hiçbir dilde yoksa buton düşer); (2) mağaza listelemesindeki 3–60 / 280 karakter kuralı yalnız ad/açıklama içindir — manifest etiketlerinde 200 karakterlik bir güvenlik sınırı vardır ve aşan değer reddedilmez, kırpılır. Alan alan kurallar Manifest Referansı'ndadır.

Portal editöründen girme

Hem mağaza metinleri (ad/açıklama) hem de manifest etiketleri — menü öğesi, aksiyon butonu, sayfa başlığı, form metinleri — dil sekmeli alanlardır. Sekmede çeviri varsa dolu, yoksa soluk bir nokta görünür; karakter sayacı seçili dilin değerini sayar.

  1. Yeni eklenti: Eklenti adı ve Açıklama alanlarında dil sekmesine tıkla, çeviriyi yaz. tr sekmesi boşken kaydedemezsin.
  2. Mevcut eklentinin metnini değiştirme: sürüm düzenleme ekranındaki Mağaza Bilgileri kartını doldur. Boş bıraktığın alan "değişiklik yok" demektir, mevcut metin korunur.
  3. Manifest etiketleri: aynı ekrandaki Menü Öğeleri, Aksiyon Butonları, Custom UI Sayfaları ve Declarative Formlar kartlarında etiket/başlık alanlarının üstündeki dil kodlarına (TR / EN / DE / RU) tıklayıp çeviriyi yaz. Burada taban dil zorunlu değildir; boş bıraktığın dil için dolu olan ilk dile düşülür.
  4. Sürümü incelemeye gönder. Öneri, sürüm onaylanıp yayınlanınca marketplace'e uygulanır.
Yayınlı bir eklentinin mağaza metni inceleme olmadan değişmez. Çeviri eklemek de bir metin değişikliğidir — yeni bir sürümle gönderilir.

MCP ile (AI ajanı)

MCP sunucusu aynı alanları araç parametresi olarak verir. Dil anahtarları katalogdan türetilir; get_catalog çıktısındaki locales bloğu desteklenen dilleri, taban dili, fallback zincirini ve uzunluk sınırlarını döner — ajan önce onu okur.

MCP — set_listing / create_plugin
# MCP aracı — sürüme çok dilli mağaza bilgisi önerisi ekler
set_listing({
  version_id: "…",
  display_name_i18n: { tr: "Kurye Entegrasyonu", en: "Courier Integration" },
  description_i18n:  { tr: "Paketleri kuryeye otomatik aktarır.", en: "Automatically dispatches packets to your courier." }
})

# Yeni eklenti oluştururken de aynı şekilde:
create_plugin({
  name: "Kurye Entegrasyonu",
  slug: "kurye-entegrasyonu",
  name_i18n: { tr: "Kurye Entegrasyonu", en: "Courier Integration" }
})
AlanTipZorunluAçıklama
set_listing.display_name_i18nobject<dil, string>–Sürüme çok dilli ad önerisi. {} gönderirsen öneri temizlenir (mevcut metin korunur).
set_listing.description_i18nobject<dil, string>–Sürüme çok dilli açıklama önerisi. {} = öneriyi temizle.
create_plugin.name_i18nobject<dil, string>–Yeni eklentinin çok dilli adı.
create_plugin.description_i18nobject<dil, string>–Yeni eklentinin çok dilli açıklaması.

Manifest tarafında da aynı harita geçerlidir: set_nav (label), set_buttons (label, confirm), set_pages (title) ve set_forms (title, submitLabel, fields[].label/help/placeholder, options[].label) dil dil değer alır. Şemalar katalogdan türediği için desteklenmeyen bir dil anahtarı araç çağrısında reddedilir.

help taşınır ama panelde görünmez. Değer sürümde saklanır ve platforma iletilir; panel şu an yalnız label ve placeholder render ediyor. Panel açtığında bu satır kaldırılacak — fields[].placeholder uçtan uca çalışıyor.
Etiket değişikliğini denerken: kurulumun anlık görüntüsü yalnız kurulum/yükseltme anında üretilir — yeni metinleri görmek için test mağazasında sürümü yükselt ya da eklentiyi kaldırıp yeniden kur. Aynısı production kurulumları için de geçerlidir.
Düz (tek dilli) display_name / description / name parametreleri çalışmaya devam eder — verilirse taban dil (tr) değeri olarak işlenir. Eski akışların hiçbiri kırılmaz; ikisi birlikte verilirse dil haritası kazanır. get_manifest ve get_plugin kayıtlı çevirileri geri okur.

En iyi pratikler

  • Önce taban dili doldur. tr her zaman dolu olsun; çeviriler onun üstüne gelir. Böylece hiçbir tenant boş başlık görmez.
  • Yarım çeviri bırakabilirsin. Yalnız en hazırsa onu ekle; eksik diller zincirle otomatik doldurulur. Bekleyip hepsini birden yayınlamak zorunda değilsin.
  • Makine çevirisine güvenme. Marketplace kartı satış metnidir; bozuk çeviri eklentinin güvenilirliğini düşürür. Emin değilsen o dili boş bırak — fallback daha iyi görünür.
  • Uzunluğu en uzun dile göre planla. Almanca/Rusça çeviriler Türkçeden belirgin uzayabilir; ad için 3–60 karakter sınırı her dilde ayrı kontrol edilir.
  • Marka adını çevirme. Eklenti adında ürün/marka kısmını sabit tut, yalnız açıklayıcı eki çevir (Acme Kurye → Acme Courier).
  • Kendi listeni türetme. Kod tarafında desteklenen dilleri SDK'nın LOCALES sabitinden import et; elle ['tr','en'] yazarsan yeni bir dil eklendiğinde sessizce geride kalırsın.

İlgili