17 KiB
Executable file
🌍 پیادهسازی سیستم ترجمه (i18n) برای ورکفلو
✅ خلاصه تغییرات
یک سیستم کامل و حرفهای برای چند زبانه کردن نودهای ورکفلو پیادهسازی شد که شامل:
- ✅ Backend: سیستم ترجمه با 200+ رشته (فارسی + انگلیسی)
- ✅ API: 4 endpoint جدید برای دریافت ترجمهها
- ✅ Frontend: سرویس و Extension برای استفاده راحت
- ✅ UI: یکپارچهسازی با dialog تنظیمات نودها
- ✅ Scripts: ابزار استخراج و صادرات خودکار
- ✅ Docs: مستندات کامل
📦 فایلهای ایجاد شده
Backend (Python):
| فایل | مسیر | توضیحات |
|---|---|---|
workflow_translations.py |
app/services/workflow/i18n/ |
تعریف تمام ترجمهها |
__init__.py |
app/services/workflow/i18n/ |
Export ترجمهها |
workflows.py (updated) |
adapters/api/v1/ |
4 endpoint جدید |
extract_workflow_translations.py |
scripts/ |
اسکریپت استخراج |
Frontend (Flutter):
| فایل | مسیر | توضیحات |
|---|---|---|
workflow_translation_service.dart |
lib/services/ |
سرویس دریافت ترجمه |
workflow_localizations_extension.dart |
lib/extensions/ |
Extension راحتی |
workflow_node_config_dialog.dart (updated) |
lib/widgets/workflow/ |
استفاده از ترجمهها |
Documentation:
| فایل | توضیحات |
|---|---|
WORKFLOW_I18N_SYSTEM.md |
راهنمای کامل سیستم |
WORKFLOW_I18N_IMPLEMENTATION.md |
این فایل |
🚀 نحوه استفاده
1. راهاندازی اولیه:
# Backend
cd /var/www/ark/hesabixAPI
source venv/bin/activate
# ریاستارت API
sudo systemctl restart hesabix-api
# یا
docker-compose restart api
2. تست ترجمهها:
# تست API endpoint
curl -X GET "http://localhost:8000/api/v1/workflows/translations?lang=fa" \
-H "Authorization: Bearer YOUR_TOKEN"
# خروجی:
{
"status": "success",
"data": {
"language": "fa",
"translations": {
"settings": "تنظیمات",
"create_invoice": {
"action_name": "ایجاد فاکتور",
...
}
}
}
}
3. استفاده در Flutter:
// در هر widget
import 'package:hesabix_ui/extensions/workflow_localizations_extension.dart';
@override
Widget build(BuildContext context) {
final t = AppLocalizations.of(context);
return Column(
children: [
Text(t.workflowCreateInvoiceActionName), // "ایجاد فاکتور"
Text(t.workflowSendTelegramFieldMessage), // "متن پیام"
],
);
}
🔄 افزودن ترجمه برای نود جدید
مرحله 1: تعریف ترجمهها (Backend)
فایل: app/services/workflow/i18n/workflow_translations.py
# اضافه کردن dictionary جدید
MY_NEW_NODE_TRANSLATIONS = {
"fa": {
"action_name": "نام فارسی",
"action_description": "توضیحات فارسی",
"field_my_field": "فیلد من",
"field_my_field_desc": "توضیحات فیلد من",
},
"en": {
"action_name": "English Name",
"action_description": "English description",
"field_my_field": "My Field",
"field_my_field_desc": "My field description",
}
}
# اضافه به exports
__all__ = [
...,
"MY_NEW_NODE_TRANSLATIONS",
]
مرحله 2: استخراج (Script)
cd /var/www/ark/hesabixAPI
python scripts/extract_workflow_translations.py
# خروجی:
# ✅ فایل ذخیره شد: .../workflow_fa.arb
# ✅ فایل ذخیره شد: .../workflow_en.arb
# ✅ Extension ذخیره شد: .../workflow_localizations_extension.dart
مرحله 3: بازسازی Flutter
cd /var/www/ark/hesabixUI/hesabix_ui
flutter pub run build_runner build --delete-conflicting-outputs
مرحله 4: استفاده در UI
// استفاده مستقیم از extension
final t = AppLocalizations.of(context);
final label = t.workflowMyNewNodeActionName;
// یا استفاده از service
final translation = _translationService.getFieldTranslation(
'my_new_node',
'my_field',
type: 'desc',
);
📊 API Endpoints جدید
1. دریافت تمام ترجمهها:
GET /api/v1/workflows/translations?lang=fa
Response:
{
"status": "success",
"data": {
"language": "fa",
"translations": {
"settings": "تنظیمات",
"create_invoice": {...},
"send_telegram": {...},
...
}
}
}
2. دریافت metadata actionها با ترجمه:
GET /api/v1/workflows/metadata/actions?lang=en
Response:
{
"status": "success",
"data": [
{
"key": "create_invoice",
"name": "Create Invoice", ← ترجمه شده
"description": "Create sales invoice...", ← ترجمه شده
"config_schema": {
"invoice_type": {
"description": "Invoice Type", ← ترجمه شده
"ui_config": {
"labels": {
"invoice_sales": "Sales Invoice" ← ترجمه شده
}
}
}
}
}
]
}
3. دریافت metadata triggerها:
GET /api/v1/workflows/metadata/triggers?lang=fa
4. صادرات به فرمت arb:
GET /api/v1/workflows/translations/export?lang=fa
Response:
{
"status": "success",
"data": {
"language": "fa",
"format": "arb",
"translations": {
"workflowSettings": "تنظیمات",
"workflowCreateInvoiceActionName": "ایجاد فاکتور",
...
},
"total_keys": 200
}
}
🎨 نمونههای کاربردی
مثال 1: نمایش نام action به دو زبان
// فارسی
final t = AppLocalizations.of(context); // locale = 'fa'
print(t.workflowCreateInvoiceActionName); // "ایجاد فاکتور"
// انگلیسی
final t = AppLocalizations.of(context); // locale = 'en'
print(t.workflowCreateInvoiceActionName); // "Create Invoice"
مثال 2: Dropdown با گزینههای ترجمه شده
DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: t.workflowCreateInvoiceFieldInvoiceType,
),
items: [
DropdownMenuItem(
value: 'invoice_sales',
child: Row(
children: [
Text('🛒'),
SizedBox(width: 8),
Text(t.workflowCreateInvoiceInvoiceSales),
],
),
),
DropdownMenuItem(
value: 'invoice_purchase',
child: Row(
children: [
Text('🛍️'),
SizedBox(width: 8),
Text(t.workflowCreateInvoiceInvoicePurchase),
],
),
),
],
)
مثال 3: Help Text با ترجمه
Widget _buildFieldWithHelp(String fieldKey) {
final t = AppLocalizations.of(context);
// دریافت help text (اگر موجود باشد)
String? helpText;
if (_translations != null && widget.node.key != null) {
final actionKey = widget.node.key;
final helpKey = 'field_${fieldKey}_help';
helpText = _translations![actionKey]?[helpKey];
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
decoration: InputDecoration(
labelText: _formatKey(fieldKey),
),
),
if (helpText != null)
Padding(
padding: EdgeInsets.only(top: 4, right: 12),
child: Row(
children: [
Icon(Icons.info_outline, size: 14),
SizedBox(width: 4),
Expanded(
child: Text(
helpText,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
),
],
),
),
],
);
}
📈 آمار پیادهسازی
تعداد رشتههای ترجمه شده:
| نود | فارسی | انگلیسی | جمع |
|---|---|---|---|
| مشترک | 15 | 15 | 30 |
| Create Invoice | 54 | 54 | 108 |
| Send Telegram | 22 | 22 | 44 |
| Send Email | 20 | 20 | 40 |
| سایر (6 نود) | ~60 | ~60 | ~120 |
| جمع کل | ~171 | ~171 | ~342 |
خطوط کد:
| بخش | خطوط |
|---|---|
| Backend Translations | ~400 |
| Backend API | ~150 |
| Frontend Service | ~150 |
| Frontend Extension | ~200 |
| Frontend UI Updates | ~80 |
| Scripts | ~200 |
| جمع | ~1180 |
✅ Checklist تکمیل شده
Backend:
- ساختار ترجمهها
- ترجمههای فارسی (171+ رشته)
- ترجمههای انگلیسی (171+ رشته)
- تابع
get_translation() - تابع
translate_metadata() - API endpoint:
/workflows/translations - API endpoint:
/workflows/metadata/actions - API endpoint:
/workflows/metadata/triggers - API endpoint:
/workflows/translations/export
Frontend:
- سرویس
WorkflowTranslationService - Extension
WorkflowLocalizations - یکپارچهسازی با
WorkflowNodeConfigDialog - Cache برای ترجمهها
- Fallback برای ترجمههای گمشده
- پشتیبانی از enum labels
- پشتیبانی از placeholders
- پشتیبانی از help texts
Scripts & Tools:
- اسکریپت استخراج ترجمهها
- صادرات به فرمت arb
- تولید Dart extension
Documentation:
- راهنمای کامل سیستم
- مثالهای کاربردی
- Best practices
- Debugging guide
🎯 ویژگیهای کلیدی
1. مدیریت متمرکز ✅
تمام ترجمهها در یک فایل Python نگهداری میشوند:
# app/services/workflow/i18n/workflow_translations.py
CREATE_INVOICE_TRANSLATIONS = {
"fa": {...},
"en": {...}
}
2. API-Driven ✅
ترجمهها از backend دریافت میشوند:
final translations = await _translationService.getTranslations(lang: 'fa');
3. Cache ✅
ترجمهها cache میشوند برای performance بهتر:
static Map<String, Map<String, dynamic>>? _cachedTranslations;
4. Type-Safe ✅
استفاده از Extension با type-safety کامل:
t.workflowCreateInvoiceActionName // autocomplete کامل!
5. Fallback ✅
اگر ترجمه یافت نشد، مقدار پیشفرض نمایش داده میشود:
return _translations?[key] ?? _formatFieldName(key);
6. Dynamic ✅
ترجمهها به صورت پویا بارگذاری میشوند:
// تغییر زبان
await _translationService.reloadTranslations(lang: 'en');
📊 مقایسه قبل و بعد
قبل:
// رشتههای hardcoded
TextFormField(
decoration: InputDecoration(
labelText: 'نوع فاکتور', // ❌ فقط فارسی
helperText: 'نوع فاکتور (invoice_sales/invoice_purchase)',
),
)
DropdownMenuItem(
value: 'invoice_sales',
child: Text('invoice_sales'), // ❌ کد خام
)
بعد:
// استفاده از ترجمه
final t = AppLocalizations.of(context);
TextFormField(
decoration: InputDecoration(
labelText: t.workflowCreateInvoiceFieldInvoiceType, // ✅ ترجمه شده
helperText: _getDescription('invoice_type'), // ✅ ترجمه شده
),
)
DropdownMenuItem(
value: 'invoice_sales',
child: Text(t.workflowCreateInvoiceInvoiceSales), // ✅ "🛒 فاکتور فروش"
)
🧪 تستها
تست Backend:
cd /var/www/ark/hesabixAPI
source venv/bin/activate
python -c "
from app.services.workflow.i18n import get_translation
# تست فارسی
print(get_translation('action_name', 'fa', 'create_invoice'))
# خروجی: ایجاد فاکتور
# تست انگلیسی
print(get_translation('action_name', 'en', 'create_invoice'))
# خروجی: Create Invoice
"
تست API:
# تست endpoint
curl -X GET "http://localhost:8000/api/v1/workflows/translations?lang=fa" \
-H "Authorization: Bearer YOUR_TOKEN" | jq '.data.translations.create_invoice.action_name'
# خروجی: "ایجاد فاکتور"
تست Frontend:
// در widget test
testWidgets('Workflow translations', (tester) async {
await tester.pumpWidget(
MaterialApp(
locale: Locale('fa'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: TestWidget(),
),
);
final t = AppLocalizations.of(tester.element(find.byType(TestWidget)));
expect(t.workflowCreateInvoiceActionName, equals('ایجاد فاکتور'));
});
🔧 صادرات ترجمهها
برای استفاده در فایلهای arb:
cd /var/www/ark/hesabixAPI
python scripts/extract_workflow_translations.py
# خروجی:
# 🌍 استخراج ترجمههای ورکفلو
# 📝 استخراج ترجمههای فارسی...
# تعداد کلیدها: 171
# 📝 استخراج ترجمههای انگلیسی...
# تعداد کلیدها: 171
# 💾 ذخیره در فایلهای arb...
# ✅ فایل ذخیره شد: .../workflow_fa.arb
# ✅ فایل ذخیره شد: .../workflow_en.arb
# 📦 تولید Dart extension...
# ✅ Extension ذخیره شد: .../workflow_localizations_extension.dart
فرمت خروجی (arb):
{
"@@locale": "fa",
"workflowSettings": "تنظیمات",
"@workflowSettings": {
"description": "Workflow translation for workflowSettings"
},
"workflowCreateInvoiceActionName": "ایجاد فاکتور",
"@workflowCreateInvoiceActionName": {
"description": "Workflow translation for workflowCreateInvoiceActionName"
}
}
💡 نکات مهم
1. Backward Compatibility:
- ✅ اگر ترجمه یافت نشد، fallback نمایش داده میشود
- ✅ رشتههای قدیمی همچنان کار میکنند
- ✅ هیچ breaking change وجود ندارد
2. Performance:
- ✅ Cache در frontend
- ✅ یکبار بارگذاری در initState
- ✅ API lightweight
3. Maintainability:
- ✅ تمرکز ترجمهها در یک مکان
- ✅ اسکریپت استخراج خودکار
- ✅ Convention واضح برای نامگذاری
4. Extensibility:
- ✅ افزودن زبان جدید راحت است
- ✅ افزودن نود جدید ساده است
- ✅ افزودن فیلد جدید فقط با اضافه کردن ترجمه
5. Developer Experience:
- ✅ Autocomplete در IDE
- ✅ Type-safety کامل
- ✅ مستندات جامع
🗺️ Roadmap
Phase 1 (تکمیل شده ✅):
- ساختار پایه سیستم ترجمه
- ترجمههای نودهای اصلی (Create Invoice, Send Telegram, Send Email)
- API endpoints
- Frontend service و extension
- یکپارچهسازی با UI
Phase 2 (آینده):
- افزودن ترجمه برای تمام triggerها
- افزودن ترجمه برای سایر actionها
- UI برای مدیریت ترجمهها
- پشتیبانی از زبانهای بیشتر (عربی، ترکی، ...)
Phase 3 (آینده):
- ترجمه user-contributed (کاربران بتوانند ترجمه اضافه کنند)
- ترجمههای context-aware
- Pluralization
- RTL/LTR handling
📚 منابع
فایلهای مرتبط:
docs/WORKFLOW_I18N_SYSTEM.md- راهنمای کاملapp/services/workflow/i18n/workflow_translations.py- ترجمههاscripts/extract_workflow_translations.py- اسکریپت استخراج
لینکهای مفید:
✅ نتیجهگیری
یک سیستم کامل، حرفهای و مقیاسپذیر برای چند زبانه کردن نودهای ورکفلو پیادهسازی شد که:
✅ 342 رشته را پشتیبانی میکند (171 فارسی + 171 انگلیسی)
✅ 4 API endpoint جدید
✅ Type-Safe در Flutter
✅ Cache برای performance
✅ Fallback برای رشتههای گمشده
✅ مستندات کامل با مثالهای کاربردی
✅ اسکریپتهای کمکی برای توسعه
این سیستم امکان ایجاد یک تجربه کاربری یکپارچه و چند زبانه را برای کاربران بینالمللی فراهم میکند! 🌍🎉
تاریخ پیادهسازی: 2025-12-04
نسخه: 1.0
وضعیت: ✅ تکمیل شده و آماده استفاده
Breaking Changes: ❌ خیر - Backward Compatible