P Pitchbar مستندات

مدیریت فضای کاری

زبان‌ها و بین‌المللی‌سازی

Pitchbar به‌صورت پیش‌فرض ترجمه‌های ۱۳۰+ زبان را ارائه می‌دهد، که زبان‌های انگلیسی، اسپانیایی، فرانسوی و ترکی به‌طور کامل پوشش داده شده‌اند و سایر زبان‌ها (آلمانی، هندی، بنگالی، عربی، عبری، چینی، ژاپنی، کرهای، ویتنامی، تمام زبان‌های رایج اروپایی/آسیایی/آفریقایی، به علاوه اسکریپت‌های راست‌چین) برای بخش‌های اصلی رابط کاربری — دکمه‌ها، ناوبری، فرم‌ها، نشان‌های وضعیت — پوشش داده شده‌اند. هر کلیدی که هنوز برای یک زبان خاص ترجمه نشده باشد، به‌طور خودکار به منبع انگلیسی بازمی‌گردد، بنابراین رابط کاربری هرگز خراب نمی‌شود در حالی که مترجمان فردی بقیه زبان‌ها را ترجمه می‌کنند.

افزودن یک زبان جدید فقط با قرار دادن یک فایل انجام می‌شود

سرویس LocaleResolver::supported() به‌طور خودکار زبان‌ها را با اسکن lang/*.json در زمان درخواست کشف می‌کند. برای افزودن یک زبان جدید، یک فایل lang/<code>.json قرار دهید (مثلاً lang/sv.json برای سوئدی) — بدون تغییر کد، بدون مهاجرت، بدون راه‌اندازی مجدد سرویس. بارگذاری بعدی صفحه آن را شناسایی می‌کند، انتخابگر آن را لیست می‌کند، میان‌افزار SetLocale ?locale=sv را می‌پذیرد و در هر پاسخ API که زبان‌های پشتیبانی‌شده را شمارش می‌کند، ظاهر می‌شود.

انتخابگر فراداده (نام بومی، نام انگلیسی، ایموجی پرچم، پرچم RTL) را از App\Services\I18n\LocaleCatalog::ENTRIES دریافت می‌کند — یک لیست گزینشی از ۱۳۰+ زبان محبوب. اگر فایل JSON را برای کدی که در کاتالوگ نیست ارسال کنید، همچنان کار می‌کند — انتخابگر به‌جای آن به خود کد، یک ایموجی 🌐 و جهت LTR بازمی‌گردد. کمک به فراداده کاتالوگ فقط ظاهر را ارتقا می‌دهد.

زبان‌های راست‌چین

کاتالوگ زبان‌های عربی، عبری، فارسی، اردو، پشتو، سندی، دیوهی، ییدیش و اویغوری را به‌عنوان RTL علامت‌گذاری می‌کند. مسیر نمایش بر این اساس تغییر می‌کند:

  • قالب‌های ریشه Blade (resources/views/app.blade.php برای برنامه SPA مدیریت، resources/views/marketing/_layout.blade.php برای سایت بازاریابی، resources/views/emails/leads/captured.blade.php برای ایمیل جذب مشتری) زمانی که ورودی کاتالوگ زبان فعال دارای rtl => true باشد، dir="rtl" را روی <html> منتشر می‌کنند.
  • ویژگی‌های منطقی Tailwind v4 چیدمان را حمل می‌کنند: هر کلاس ابزار ms-/me-/ps-/pe-/start-/end-/text-start/text-end براساس جهت سند به‌طور خودکار تغییر می‌کند. کدبیس منحصراً از ویژگی‌های منطقی استفاده می‌کند؛ کلاس‌های فیزیکی ml-/mr-/pl-/pr-/left-/right- توسط یک codemod قبلی حذف شده‌اند.
  • یک <DirectionProvider> Radix برنامه React را در resources/js/app.tsx می‌پوشاند، بنابراین هر عنصر اصلی Radix (DropdownMenu، Popover، Tooltip، Select، Sheet، ContextMenu) تراز + جهت انیمیشن صحیح را بدون کد در هر کامپوننت دریافت می‌کند.
  • قلاب‌های useIsRtl() / useDirection() در resources/js/lib/direction.ts پرچم RTL زبان فعلی را از کاتالوگ i18n مشترک می‌خوانند. زمانی که یک کامپوننت به منطق جهت صریح JS نیاز دارد، از آنها استفاده کنید.
  • آیکون‌های جهت‌دار (بازگشت، جلو، شورون‌ها) با <DirArrow direction="forward|back" /> از resources/js/components/dir-icon.tsx پیچیده می‌شوند تا خود آیکون تغییر کند. آیکون‌هایی که جهت آنها تزئینی است (ارسال هواپیما‌کاغذی، بازگردانی) به‌جای تعویض گلیف‌ها از کلاس CSS .flip-rtl استفاده می‌کنند.
  • ویجت بازدیدکننده init.agent.locale را در زمان راه‌اندازی خوانده و اگر زبان RTL باشد، dir="rtl" را روی ریشه سایه خود تنظیم می‌کند — هر کلاس ویژگی منطقی Tailwind در داخل ویجت سپس مانند برنامه SPA مدیریت تغییر می‌کند.
  • کامپوننت <Sidebar> ویژگی side خود را به‌طور پیش‌فرض روی لبه شروع بصری براساس جهت تنظیم می‌کند (side="left" در LTL، side="right" در RTL)، بنابراین یک <Sidebar /> معمولی همیشه به شروع بصری متصل می‌شود.

تست بازگشتی tests/Feature/I18n/RtlDirTest.php تأیید می‌کند که هر زبان RTL dir="rtl" را روی ریشه اینرسی مدیریت، چیدمان بازاریابی و ایمیل جذب مشتری تولید می‌کند؛ زبان‌های LTR برعکس dir="ltr" تولید می‌کنند.

انتخابگر زبان

هم پوسته مدیریت و هم سایت بازاریابی زمانی که روی نشان زبان کلیک می‌کنید، یک Dialog قابل جستجو باز می‌کنند. لیست نام بومی + نام انگلیسی + پرچم را برای هر زبان نشان می‌دهد که براساس کد یا نام قابل فیلتر است. همان کامپوننت در هر دو سطح. با ۱۳۰+ ورودی، منوی کشویی قدیمی غیرقابل اسکرول بود — این مودال تا هزاران زبان مقیاس می‌شود.

ترتیب حل

میان‌افزار SetLocale پس از میان‌افزار نشست در هر درخواست وب اجرا شده و این لیست اولویت را طی می‌کند:

  1. پرسش صریح ?locale=<slug> (لیست مجاز).
  2. ستون users.locale کاربر احراز هویت‌شده.
  3. کوکی pb_locale (تنظیم‌شده توسط مسیر تعویض بنر جغرافیایی، برای بازدیدکنندگان احراز هویت‌نشده در بین نشست‌ها باقی می‌ماند).
  4. هدر Accept-Language مرورگر (بالاترین q-value برنده است).
  5. پیش‌فرض برنامه از config/app.php.

بنر زبان پیشنهادی براساس موقعیت جغرافیایی

زمانی که هدر CF-IPCountry کلودفلر به یک زبانی که ما ارائه می‌دهیم نگاشت می‌شود و زبان فعلی بازدیدکننده چیز دیگری است، یک بنر باریک با این سوال ظاهر می‌شود: "به Español تغییر دهید؟" بنر هرگز به‌طور خودکار تغییر نمی‌کند — غافلگیری = تجربه کاربری بد. دو اقدام:

  • تغییر به <زبان> — درخواست PATCH به /locale/switch. users.locale را در صورت وارد بودن تنظیم کرده و کوکی pb_locale را همیشه تنظیم می‌کند (عمر ۱ سال)، سپس در زبان جدید بارگذاری مجدد می‌کند.
  • — درخواست POST به /locale/dismiss-suggestion، کوکی pb_locale_dismiss=1 را تنظیم می‌کند (عمر ۱۸۰ روز). بنر هرگز در آن دستگاه دوباره ظاهر نمی‌شود.

قوانین سرکوب (سمت سرور، در LocaleResolver::suggestionFor):

  1. بازدیدکننده قبلاً رد کرده است → null.
  2. زبان فعلی قبلاً با پیشنهاد مطابقت دارد → null.
  3. هدر CF-IPCountry وجود ندارد (توسعه محلی، استقرارهای غیر CF) یا مقدار XX/T1 است → null.
  4. کشور در COUNTRY_TO_LOCALE نیست → null.

نقشه کشور → زبان، آمریکای لاتین اسپانیایی‌زبان + اسپانیا (es)، اروپای فرانسوی + کبک (fr)، ترکیه (tr) را پوشش می‌دهد. سایر کشورها پیشنهادی دریافت نمی‌کنند.

بنر در برنامه SPA مدیریت (app-sidebar-layout)، در هر صفحه اینرسی بازاریابی (marketing-shell) و از طریق Blade {{ __('Switch to :language?') }} در resources/views/marketing/_layout.blade.php برای هر صفحه بازاریابی نمایش داده شده توسط Blade در آینده نصب می‌شود.

همان سرویس LocaleResolver ویجت را نیز تغذیه می‌کند. عبور ویجت یک مرحله اضافی در بالا اضافه می‌کند: language_default دستیار فروش — مدیران می‌توانند یک زبان خاص عمودی را حتی اگر مرورگر بازدیدکننده مخالف باشد، قفل کنند.

محل قرارگیری رشته‌ها

  • lang/{locale}.json — دیکشنری JSON که توسط برنامه SPA React مدیریت، ویجت، صفحات Blade بازاریابی و قالب‌های ایمیل استفاده می‌شود. رشته‌های منبع انگلیسی به‌عنوان کلید عمل می‌کنند.
  • lang/{locale}/auth.php، validation.php، passwords.php، pagination.php — فایل‌های PHP نام‌فضایی لاراول برای پیام‌های چارچوب داخلی.
  • lang/_glossary.md — قفل اصطلاحات تا رشته‌های آینده به‌طور مداوم با اجراهای قبلی ترجمه شوند.

محل افزودن ترجمه‌ها

هر زمان که یک رشته رو به کاربر در کد اضافه می‌کنید:

  • بک‌اند Blade: با منبع انگلیسی بپیچید.
  • مدیریت React: قلاب را وارد کرده و const { t } = useT(); را فراخوانی کنید، سپس t('English source').
  • ویجت: t را از core/i18n.ts وارد کرده و t('English source') را فراخوانی کنید. کلید را به WidgetCopy::KEYS اضافه کنید تا سرور آن را به payload /init تبدیل کند.

کلیدهای ترجمه‌شده به lang/<locale>.json اضافه می‌شوند. کلیدهای گم‌شده به‌طور بی‌صدا به منبع انگلیسی بازمی‌گردند — رابط کاربری هرگز خراب نمی‌شود. تست بازگشتی tests/Feature/I18nTest::every supported locale ships a parseable JSON dictionary تأیید می‌کند که هر فایل زبان ارسال‌شده JSON معتبر با مقادیر رشته غیرخالی است؛ یک تست دیگر از کلیدهای ناشی از تایپ اشتباه جلوگیری می‌کند (هر کلید در یک فایل زبان که در en.json وجود ندارد، CI را با شکست مواجه می‌کند).

افزودن یک زبان جدید

  1. یک فایل lang/<slug>.json قرار دهید. این به‌تنهایی باعث می‌شود زبان در انتخابگر ظاهر شده و ?locale=<slug> را از طریق میان‌افزار SetLocale بپذیرد. LocaleResolver::supported() به‌طور خودکار فایل را در درخواست بعدی کشف می‌کند.
  2. (اختیاری، اما توصیه می‌شود) یک ورودی در app/Services/I18n/LocaleCatalog::ENTRIES با نام native زبان، نام english، ایموجی flag و پرچم rtl اضافه کنید. بدون ورودی، انتخابگر همچنان کار می‌کند — فقط کد زبان را به‌عنوان برچسب و یک کره 🌐 نشان می‌دهد.
  3. (اختیاری) lang/en/{auth,validation,passwords,pagination}.php را در lang/<slug>/ کپی کنید اگر می‌خواهید پیام‌های Fortify / اعتبارسنجی ترجمه شوند. بدون این فایل‌ها، لاراول به انگلیسی بازمی‌گردد.
  4. php artisan test --filter=I18nTest و --filter=LocaleResolverTest را اجرا کنید تا تأیید کنید زبان جدید کلیدهای فانتوم معرفی نمی‌کند.
  5. (اختیاری) lang/_glossary.md را با یک ستون به‌روز کنید تا ترجمه‌های آینده منسجم بمانند.

برای فعالسازی یک زبان نیازی به تغییر کد نیست. ثابت قبلی LocaleResolver::SUPPORTED حذف شده است؛ انتخابگر، قوانین اعتبارسنجی و میان‌افزار همه از LocaleResolver::supported() می‌خوانند که مجموعه کشف‌شده خودکار را برمی‌گرداند.

زبان به‌ازای هر کاربر در مقابل به‌ازای هر بازدیدکننده

مدیران و اپراتورها زبان ترجیحی خود را در /settings/locale تنظیم می‌کنند. انتخاب در users.locale ذخیره شده و در هر درخواست بعدی، از جمله ایمیل‌های ارسال‌شده به نمایندگی از آنها، اعمال می‌شود.

بازدیدکنندگان به‌طور پیش‌فرض language_default دستیار فروش را می‌بینند. اگر دستیار فروش زبانی را قفل نکرده باشد، ویجت به زبان مرورگر بازدیدکننده و سپس به انگلیسی بازمی‌گردد. هیچ انتخابگر زبان درون ویجتی وجود ندارد — این یک تصمیم عمدی است تا تجربه بازدیدکننده با آنچه مدیر پیکربندی کرده است مطابقت داشته باشد.

پوشش

هر سطح رو به مشتری — ویجت بازدیدکننده، سایت بازاریابی (خانه، قیمت‌گذاری، نحوه عملکرد، یکپارچه‌سازی‌ها، تاریخچه تغییرات، حریم خصوصی، شرایط)، برنامه SPA مدیریت (هر صفحه مدیریت مشتری و مدیریت پلتفرم شامل سفارشی‌سازی دستیار فروش، منابع، پاسخ‌های دستی، دانش، محیط آزمایشی، رفتار، فراخوان‌ها، مشتریان، مکالمات، آزمایش‌ها، صورتحساب، یکپارچه‌سازی‌ها، تحلیل‌ها، فرآیندهای خودکار، هر زبانه تنظیمات)، جریان‌های احراز هویت + شروع کار، ایمیل‌های تراکنشی و پیام‌های اعتبارسنجی — از طریق useT() یا __() متصل شده است. منبع انگلیسی (lang/en.json) منبع حقیقت است و در حال حاضر حدود ۲,۳۰۰ کلید دارد.

پوشش هر زبان متفاوت است. en، es، fr و tr به‌طور کامل از ابتدا تا انتها ترجمه شده‌اند (هر کلید در en.json یک مقدار محلی دارد). سایر فایل‌های زبان کشف‌شده حدود ۱۳۰+ با رایج‌ترین بخش‌های اصلی رابط کاربری ترجمه‌شده شروع می‌شوند (حدود ۱۳۰ کلید: دکمه‌ها، ناوبری، فرم‌ها، نشان‌های وضعیت) و از آنجا با کمک مترجمان گسترش می‌یابند. کلیدهایی که هنوز برای یک زبان خاص ترجمه نشده‌اند، از طریق رفتار استاندارد کلید JSON لاراول به منبع انگلیسی بازمی‌گردند، بنابراین رابط کاربری هرگز خراب نمی‌شود؛ کاربران ترجمه جزئی را در حالی که بقیه زبان‌ها تکمیل می‌شود، می‌بینند.

برای بررسی پوشش یک زبان در هر زمان:

node -e 'const fs=require("fs"); const en=JSON.parse(fs.readFileSync("lang/en.json")); const m=JSON.parse(fs.readFileSync("lang/<code>.json")); const total=Object.keys(en).length; const translated=Object.keys(en).filter(k=>k in m && m[k]!==en[k]).length; console.log(`${translated}/${total} = ${Math.round(translated/total*100)}% covered`);'

صفحات مستندات در resources/views/documentation/pages/ به‌طور سیاستی به انگلیسی باقی می‌مانند — ترجمه نوشته‌های فنی دقیق یک پروژه کپی‌رایتینگ است، نه مهندسی. اگر یک معامله خاص به مستندات ترجمه‌شده نیاز دارد، پیگیری را در تخته کانبان دنبال کنید.

SEO + دسترسی‌پذیری مرورگر

  • ویژگی <html lang> در چیدمان بازاریابی، ریشه اینرسی مدیریت و ایمیل‌های تراکنشی، زبان حل‌شده را در هر بار نمایش منعکس می‌کند.
  • پیام‌های اعتبارسنجی، ایمیل‌های بازنشانی رمز عبور و پیام‌های احراز هویت Fortify همه از مترجم لاراول عبور می‌کنند — آنها به‌طور خودکار زبان کاربر را دریافت می‌کنند.
  • اولین نمایش ویجت قبلاً به زبان صحیح صحبت می‌کند — سرور agent.copy را در زمان /init تولید می‌کند، بنابراین هرگز لحظه‌ای از فلش انگلیسی قبل از تولید کپی ترجمه‌شده وجود ندارد.

زبان خود را انتخاب کنید