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.
tr) metni görünür — yani çeviri eklemek hiçbir şeyi bozmaz, yalnızca hazır olursun.| Kod | Dil | Rol |
|---|---|---|
| tr | Türkçe | Taban dil — zorunlu, fallback zincirinin ikinci halkası |
| en | English | Opsiyonel çeviri |
| de | Deutsch | Opsiyonel ç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.
Bir dil haritasından gösterilecek metin her yerde aynı sırayla seçilir (panel, portal, çalışma zamanı ve veritabanı aynı zinciri uygular):
map[locale]map["tr"]tr, en, de, ru) ilk dolu değer — deterministiktir, JSON anahtar sırasına bağlı değildir""){ "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):
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 doluKendi Custom UI sayfanda kullanıcının dilini App Bridge getContext verir:
// 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);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).
{
"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."
}
}| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| display_name_i18n | object<dil, string> | ✓ | Eklenti adı. Her dil değeri 3–60 karakter. Taban dil tr zorunlu. |
| description_i18n | object<dil, string> | – | Marketplace kartı açıklaması. Her dil değeri en fazla 280 karakter. Tamamen boş bırakılabilir. |
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.Çoklu dil yeni bir mekanizma değildir — manifest'te zaten kullanılıyor. Aynı dil haritası şekli şu alanlarda geçerlidir:
nav[].label — sol menü öğesinin adıpages[].title — Custom UI sayfa başlığıbuttons[].label ve buttons[].confirm — aksiyon butonu metinleriforms[].title, forms[].fields[].label, forms[].submitLabel — declarative form metinleri"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"
}
]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.
tr sekmesi boşken kaydedemezsin.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 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" }
})| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| set_listing.display_name_i18n | object<dil, string> | – | Sürüme çok dilli ad önerisi. {} gönderirsen öneri temizlenir (mevcut metin korunur). |
| set_listing.description_i18n | object<dil, string> | – | Sürüme çok dilli açıklama önerisi. {} = öneriyi temizle. |
| create_plugin.name_i18n | object<dil, string> | – | Yeni eklentinin çok dilli adı. |
| create_plugin.description_i18n | object<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.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.tr her zaman dolu olsun; çeviriler onun üstüne gelir. Böylece hiçbir tenant boş başlık görmez.en hazırsa onu ekle; eksik diller zincirle otomatik doldurulur. Bekleyip hepsini birden yayınlamak zorunda değilsin.Acme Kurye → Acme Courier).LOCALES sabitinden import et; elle ['tr','en'] yazarsan yeni bir dil eklendiğinde sessizce geride kalırsın.resolveLocalized, LOCALES, LocalizedTextset_listing / create_plugin