import 'package:flutter/widgets.dart'; import 'package:worker/generated/l10n/app_localizations.dart'; /// Extension for easy access to AppLocalizations /// /// This extension provides convenient access to localization strings /// throughout the app without having to write `AppLocalizations.of(context)!` /// every time. /// /// Usage: /// ```dart /// // Instead of: /// Text(AppLocalizations.of(context)!.login) /// /// // You can use: /// Text(context.l10n.login) /// ``` extension L10nExtension on BuildContext { /// Get the current AppLocalizations instance /// /// This getter provides quick access to all localized strings. /// It will throw an error if called before the app is initialized, /// which helps catch localization issues during development. AppLocalizations get l10n => AppLocalizations.of(this)!; /// Get the current locale language code (e.g., 'vi', 'en') String get languageCode => Localizations.localeOf(this).languageCode; /// Check if the current locale is Vietnamese bool get isVietnamese => languageCode == 'vi'; /// Check if the current locale is English bool get isEnglish => languageCode == 'en'; } /// Helper class for common localization patterns /// /// This class provides utility methods for formatting dates, times, /// currencies, and other locale-specific data. class L10nHelper { const L10nHelper._(); /// Format a DateTime to localized date string (DD/MM/YYYY for Vietnamese, MM/DD/YYYY for English) /// /// Example: /// ```dart /// final dateStr = L10nHelper.formatDate(context, DateTime.now()); /// // Vietnamese: "17/10/2025" /// // English: "10/17/2025" /// ``` static String formatDate(BuildContext context, DateTime date) { final day = date.day.toString().padLeft(2, '0'); final month = date.month.toString().padLeft(2, '0'); final year = date.year.toString(); return context.l10n.formatDate(day, month, year); } /// Format a DateTime to localized date-time string /// /// Example: /// ```dart /// final dateTimeStr = L10nHelper.formatDateTime(context, DateTime.now()); /// // Vietnamese: "17/10/2025 lúc 14:30" /// // English: "10/17/2025 at 14:30" /// ``` static String formatDateTime(BuildContext context, DateTime dateTime) { final day = dateTime.day.toString().padLeft(2, '0'); final month = dateTime.month.toString().padLeft(2, '0'); final year = dateTime.year.toString(); final hour = dateTime.hour.toString().padLeft(2, '0'); final minute = dateTime.minute.toString().padLeft(2, '0'); return context.l10n.formatDateTime(day, month, year, hour, minute); } /// Format a number as Vietnamese Dong currency /// /// Example: /// ```dart /// final price = L10nHelper.formatCurrency(context, 1500000); /// // Returns: "1.500.000 ₫" /// ``` static String formatCurrency(BuildContext context, double amount) { final formatted = context.isVietnamese ? _formatNumberVietnamese(amount) : _formatNumberEnglish(amount); return context.l10n.formatCurrency(formatted); } /// Format number with Vietnamese grouping (dots) static String _formatNumberVietnamese(double number) { final parts = number.toStringAsFixed(0).split('.'); final intPart = parts[0]; // Add dots every 3 digits from right final buffer = StringBuffer(); for (var i = 0; i < intPart.length; i++) { if (i > 0 && (intPart.length - i) % 3 == 0) { buffer.write('.'); } buffer.write(intPart[i]); } return buffer.toString(); } /// Format number with English grouping (commas) static String _formatNumberEnglish(double number) { final parts = number.toStringAsFixed(0).split('.'); final intPart = parts[0]; // Add commas every 3 digits from right final buffer = StringBuffer(); for (var i = 0; i < intPart.length; i++) { if (i > 0 && (intPart.length - i) % 3 == 0) { buffer.write(','); } buffer.write(intPart[i]); } return buffer.toString(); } /// Format a relative time (e.g., "5 minutes ago", "2 days ago") /// /// Example: /// ```dart /// final relativeTime = L10nHelper.formatRelativeTime( /// context, /// DateTime.now().subtract(Duration(minutes: 5)), /// ); /// // Returns: "5 phút trước" (Vietnamese) or "5 minutes ago" (English) /// ``` static String formatRelativeTime(BuildContext context, DateTime dateTime) { final now = DateTime.now(); final difference = now.difference(dateTime); if (difference.inSeconds < 60) { return context.l10n.justNow; } else if (difference.inMinutes < 60) { return context.l10n.minutesAgo(difference.inMinutes); } else if (difference.inHours < 24) { return context.l10n.hoursAgo(difference.inHours); } else if (difference.inDays < 7) { return context.l10n.daysAgo(difference.inDays); } else if (difference.inDays < 30) { return context.l10n.weeksAgo((difference.inDays / 7).floor()); } else if (difference.inDays < 365) { return context.l10n.monthsAgo((difference.inDays / 30).floor()); } else { return context.l10n.yearsAgo((difference.inDays / 365).floor()); } } /// Get localized order status string static String getOrderStatus(BuildContext context, String status) { switch (status.toLowerCase()) { case 'pending': return context.l10n.pending; case 'processing': return context.l10n.processing; case 'shipping': return context.l10n.shipping; case 'completed': return context.l10n.completed; case 'cancelled': return context.l10n.cancelled; default: return status; } } /// Get localized project status string static String getProjectStatus(BuildContext context, String status) { switch (status.toLowerCase()) { case 'planning': return context.l10n.planningProjects; case 'in_progress': case 'inprogress': return context.l10n.inProgressProjects; case 'completed': return context.l10n.completedProjects; default: return status; } } /// Get localized member tier string static String getMemberTier(BuildContext context, String tier) { switch (tier.toLowerCase()) { case 'diamond': return context.l10n.diamond; case 'platinum': return context.l10n.platinum; case 'gold': return context.l10n.gold; default: return tier; } } /// Get localized user type string static String getUserType(BuildContext context, String userType) { switch (userType.toLowerCase()) { case 'contractor': return context.l10n.contractor; case 'architect': return context.l10n.architect; case 'distributor': return context.l10n.distributor; case 'broker': return context.l10n.broker; default: return userType; } } /// Get localized password strength string static String getPasswordStrength(BuildContext context, String strength) { switch (strength.toLowerCase()) { case 'weak': return context.l10n.weak; case 'medium': return context.l10n.medium; case 'strong': return context.l10n.strong; case 'very_strong': case 'verystrong': return context.l10n.veryStrong; default: return strength; } } /// Format points with proper pluralization /// /// Example: /// ```dart /// final pointsText = L10nHelper.formatPoints(context, 100); /// // Returns: "+100 điểm" (Vietnamese) or "+100 points" (English) /// ``` static String formatPoints( BuildContext context, int points, { bool showSign = true, }) { if (showSign && points > 0) { return context.l10n.earnedPoints(points); } else if (showSign && points < 0) { return context.l10n.spentPoints(points.abs()); } else { return context.l10n.pointsBalance(points); } } /// Format item count with pluralization static String formatItemCount(BuildContext context, int count) { return context.l10n.itemsInCart(count); } /// Format order count with pluralization static String formatOrderCount(BuildContext context, int count) { return context.l10n.ordersCount(count); } /// Format project count with pluralization static String formatProjectCount(BuildContext context, int count) { return context.l10n.projectsCount(count); } /// Format days remaining with pluralization static String formatDaysRemaining(BuildContext context, int days) { return context.l10n.daysRemaining(days); } }