|
2 | 2 | * Utility functions for ObjectStack Console |
3 | 3 | */ |
4 | 4 |
|
| 5 | +import type { NavigationItem } from '@object-ui/types'; |
| 6 | + |
5 | 7 | /** |
6 | 8 | * Resolves an I18nLabel to a plain string. |
7 | 9 | * I18nLabel can be either a string or an object { key, defaultValue?, params? }. |
8 | | - * When it's an object, we return the defaultValue or the key as fallback. |
| 10 | + * When it's an object and a `t` function is provided, it looks up the key |
| 11 | + * in the i18n system. Otherwise it returns the defaultValue or the key as fallback. |
9 | 12 | */ |
10 | | -export function resolveI18nLabel(label: string | { key: string; defaultValue?: string; params?: Record<string, any> } | undefined): string | undefined { |
| 13 | +export function resolveI18nLabel( |
| 14 | + label: string | { key: string; defaultValue?: string; params?: Record<string, any> } | undefined, |
| 15 | + t?: (key: string, options?: any) => string, |
| 16 | +): string | undefined { |
11 | 17 | if (label === undefined || label === null) return undefined; |
12 | 18 | if (typeof label === 'string') return label; |
| 19 | + if (t) return t(label.key, { defaultValue: label.defaultValue, ...label.params }); |
13 | 20 | return label.defaultValue || label.key; |
14 | 21 | } |
15 | 22 |
|
| 23 | +// --------------------------------------------------------------------------- |
| 24 | +// CRM Navigation i18n helpers |
| 25 | +// --------------------------------------------------------------------------- |
| 26 | + |
| 27 | +/** |
| 28 | + * Map from CRM navigation item IDs to CRM i18n `navigation.*` keys. |
| 29 | + * This allows translating navigation labels when the user switches locale. |
| 30 | + */ |
| 31 | +const CRM_NAV_I18N_MAP: Record<string, string> = { |
| 32 | + nav_dashboard: 'dashboard', |
| 33 | + nav_contacts: 'contacts', |
| 34 | + nav_accounts: 'accounts', |
| 35 | + nav_opportunities: 'opportunities', |
| 36 | + nav_pipeline: 'pipeline', |
| 37 | + nav_projects: 'projects', |
| 38 | + nav_events: 'calendar', |
| 39 | + nav_sales: 'sales', |
| 40 | + nav_orders: 'orders', |
| 41 | + nav_products: 'products', |
| 42 | + nav_order_items: 'lineItems', |
| 43 | + nav_reports: 'reports', |
| 44 | + nav_sales_report: 'salesReport', |
| 45 | + nav_pipeline_report: 'pipelineReport', |
| 46 | + nav_getting_started: 'gettingStarted', |
| 47 | + nav_settings: 'settings', |
| 48 | + nav_help: 'help', |
| 49 | +}; |
| 50 | + |
| 51 | +/** |
| 52 | + * Recursively translate navigation item labels using CRM i18n keys. |
| 53 | + * Falls back to the original label when no translation is found. |
| 54 | + */ |
| 55 | +export function translateCrmNavigation( |
| 56 | + items: NavigationItem[], |
| 57 | + t: (key: string, options?: any) => string, |
| 58 | +): NavigationItem[] { |
| 59 | + return items.map((item) => { |
| 60 | + const i18nKey = CRM_NAV_I18N_MAP[item.id]; |
| 61 | + const translatedLabel = i18nKey |
| 62 | + ? t(`crm.navigation.${i18nKey}`, { defaultValue: item.label }) |
| 63 | + : item.label; |
| 64 | + return { |
| 65 | + ...item, |
| 66 | + label: translatedLabel, |
| 67 | + children: item.children |
| 68 | + ? translateCrmNavigation(item.children, t) |
| 69 | + : undefined, |
| 70 | + }; |
| 71 | + }); |
| 72 | +} |
| 73 | + |
| 74 | +/** |
| 75 | + * Map from CRM dashboard widget IDs to CRM i18n `dashboard.widgets.*` keys. |
| 76 | + */ |
| 77 | +const CRM_WIDGET_I18N_MAP: Record<string, string> = { |
| 78 | + total_revenue: 'totalRevenue', |
| 79 | + active_deals: 'activeDeals', |
| 80 | + win_rate: 'winRate', |
| 81 | + avg_deal_size: 'avgDealSize', |
| 82 | + revenue_trends: 'revenueTrends', |
| 83 | + lead_source: 'leadSource', |
| 84 | + pipeline_by_stage: 'pipelineByStage', |
| 85 | + top_products: 'topProducts', |
| 86 | + recent_opportunities: 'recentOpportunities', |
| 87 | + revenue_by_account: 'revenueByAccount', |
| 88 | + avg_deal_by_stage: 'avgDealSizeByStage', |
| 89 | + orders_by_status: 'ordersByStatus', |
| 90 | +}; |
| 91 | + |
| 92 | +/** |
| 93 | + * Translate CRM dashboard widget titles using CRM i18n keys. |
| 94 | + * Falls back to the original title when no translation is found. |
| 95 | + */ |
| 96 | +export function translateCrmDashboardWidgets( |
| 97 | + widgets: any[], |
| 98 | + t: (key: string, options?: any) => string, |
| 99 | +): any[] { |
| 100 | + return widgets.map((widget) => { |
| 101 | + const i18nKey = CRM_WIDGET_I18N_MAP[widget.id]; |
| 102 | + if (!i18nKey) return widget; |
| 103 | + return { |
| 104 | + ...widget, |
| 105 | + title: t(`crm.dashboard.widgets.${i18nKey}`, { defaultValue: widget.title }), |
| 106 | + }; |
| 107 | + }); |
| 108 | +} |
| 109 | + |
16 | 110 | /** |
17 | 111 | * Format a record title using the titleFormat pattern |
18 | 112 | * @param titleFormat Pattern like "{name} - {email}" or "{firstName} {lastName}" |
|
0 commit comments