التوطين

كل نص مدمج في العدة (468 تسمية عبر 77 مجموعة تسميات: aria-label، وإعلانات قارئ الشاشة، ونصوص الأزرار التي لم تكتبها، والنصوص النائبة) يترجمه provider واحد. ركّبه مرة واحدة بحزمة لغوية فيتحدث كل مكوّن من goodui تلك اللغة؛ وتتبعها تنسيقات الأرقام والتواريخ والعملات عبر Intl، وتأخذ العربية والعبرية اتجاههما. التطبيقات التي لا تضبطه تبقى بالإنجليزية وتنسيقات en-US، بلا أي تحميل إضافي.

التثبيت

npx shadcn@latest add https://goodui.dev/r/locale.json https://goodui.dev/r/locale-tr.json

يصل locale إلى lib/goodui-locale.ts (كل مكوّن له تسميات يعتمد عليه أصلًا، فغالبًا هو لديك). تصل الحزمة إلى lib/goodui-locales/<lang>.ts ولا تعتمد على شيء آخر؛ ثبّت اللغات التي تشحنها فقط.

ضبط اللغة

app/layout.tsx
import { GooduiLocaleProvider } from "@/lib/goodui-locale"
import tr from "@/lib/goodui-locales/tr"

export default function RootLayout({ children }) {
  return (
    <html lang="tr">
      <body>
        <GooduiLocaleProvider lang="tr" labels={tr}>{children}</GooduiLocaleProvider>
      </body>
    </html>
  )
}

lang وسم BCP 47 ويقود كل تنسيق Intl في العدة ("de-AT", "pt-BR", "en-GB" مقبولة). labels هي الحزمة. لمبدّل لغات، احتفظ بالوسم في الحالة واختر الحزمة من خريطة استيرادات كسولة؛ وتعمل الـ providers المتداخلة، فيمكن لشاشة واحدة أن تعمل بلغة أخرى.

الحزم

18 لغة، ملف واحد لكل منها، وكل تسمية لكل مكوّن. الأسماء الأصلية كما يعرضها المبدّل:

  • locale-tr: Türkçe
  • locale-de: Deutsch
  • locale-fr: Français
  • locale-es: Español
  • locale-it: Italiano
  • locale-pt-BR: Português (Brasil)
  • locale-nl: Nederlands
  • locale-pl: Polski
  • locale-ru: Русский
  • locale-hi: हिन्दी
  • locale-id: Bahasa Indonesia
  • locale-vi: Tiếng Việt
  • locale-th: ไทย
  • locale-ja: 日本語
  • locale-ko: 한국어
  • locale-zh-CN: 中文(简体)
  • locale-ar: العربية (RTL)
  • locale-he: עברית (RTL)

locale-en موجود أيضًا: يُولَّد من المكونات وتُفحص كل الحزم الأخرى مقابله. استورده حين تريد تغيير التسميات الإنجليزية على مستوى التطبيق.

RTL

تقرأ المكونات اتجاه الكتابة من DOM (خصائص منطقية، :dir(rtl)، أيقونات معكوسة)، فاضبطه على المستند بنفسك: <html lang="ar" dir="rtl">. لا يلمس provider وسم <html> أبدًا؛ هو يشتق dir من lang فقط (ar وhe وfa وur من اليمين إلى اليسار) للمكونات التي تطلبه، ويمكنك تمرير dir لتجاوزه. dirOf("ar") مُصدَّر لكود التخطيط الخاص بك.

تنسيقات Intl

المكونات التي تنسّق القيم (number-flow وcounter-up وstat-card وmeter وsparkline-draw وdata-grid وdate-picker وnumber-input) تأخذ خاصية locale. إن لم تُضبط، فهي الآن لغة provider بدلًا من "en-US"؛ والخاصية الصريحة تبقى هي الغالبة. المنسّقات نفسها متاحة لك عبر hook:

import { useGooduiLocale } from "@/lib/goodui-locale"

const { lang, dir, formatNumber, formatDate, formatRelative, formatCurrency } = useGooduiLocale()

formatNumber(12345.6)                       // "12.345,6" in de
formatDate(booking.start)                   // "3 Kas 2026" in tr; pass Intl.DateTimeFormat options for other styles
formatRelative(-2, "hour")                  // "vor 2 Stunden"
formatCurrency(49, "EUR")                   // "49,00 €"

تُخزَّن النسخ مؤقتًا لكل لغة وخيارات، فاستدعاؤها داخل render لا بأس به. خارج React، يعيد createFormatters(lang) الدوال الأربع نفسها.

تجاوز تسمية واحدة

خاصية labels على أي مكوّن تبقى غالبة على الحزمة، فيمكن لنسخة واحدة أن تقول شيئًا آخر. لتغيير على مستوى التطبيق، انشر الحزمة:

<Dialog labels={{ confirm: "Rezervasyonu iptal et" }} … />        {/* this dialog only */}

const labels = { ...tr, alert: { ...tr.alert, dismiss: "Kapat" } }   // every alert
<GooduiLocaleProvider lang="tr" labels={labels}>

التسميات ذات القيم دوال، فالجمع حقيقي: results: (n) => plural("pl", n, { one: "1 wynik", few: `${n} wyniki`, many: `${n} wyników`, other: `${n} wyniku` }). يأتي plural() في lib/goodui-locale ويغلّف Intl.PluralRules.

إضافة لغة

انسخ lib/goodui-locales/en.ts إلى ملف جديد وترجم القيم؛ أبقِ المفاتيح وتوقيعات الدوال. يسرد البيان، lib/locales/labels-manifest.json في المستودع، كل مفتاح مع نوعه ومعاملاته وموضع استخدامه (aria-label، قارئ الشاشة، نص مرئي). يشغّل بناؤنا node scripts/extract-labels.ts، الذي يعيد توليد lib/goodui-locales/en.ts من المكونات ويفشل حين تنقص أي حزمة مكوّنًا أو مفتاحًا أو معاملًا، فلا يمكن للحزم الـ 18 أن تتخلف عن المكونات أبدًا. طلبات السحب بلغات جديدة مرحّب بها.

جرّبه

في Playground كل مكوّن من Core قائمة لاختيار اللغة: تُعاد المعاينة بتلك اللغة (RTL للعربية والعبرية) ويتضمن المقتطف المطبوع الـ provider. أي صفحة معاينة تقبل ?lang=tr (و&dir=rtl لفرض اتجاه)، مثلًا /preview/c/pagination?lang=ar.

goodui Native

الحزم والبيان نفسها مخطط لها في عدة React Native (LocaleProvider في foundation، ومعرّفات المكونات نفسها)؛ حتى ذلك الحين، تأخذ مكونات Native نصوصها عبر props وكائنات labels لكل شاشة.