mena 1.0.1
mena: ^1.0.1 copied to clipboard
Comprehensive offline MENA country data with Arabic-first localization, ISO codes, currencies, and dial codes. Includes automatic locale switching and Arabic/English support.
MENA #
Comprehensive offline MENA country data with localized names, ISO codes, currencies, and dial codes.
Perfect for building country selectors, phone number inputs, currency converters, and international applications targeting the Middle East and North Africa region.
📑 Table of Contents #
- ✨ Features
- 🚀 Quick Start
- 🏴 Flag System
- 📚 API Reference
- 💡 Usage Examples
- 🌍 Supported Countries
- 📱 Platform Support
- 🤝 Contributing
- 📄 License
- 🔗 Links
- ⭐ Support
✨ Features #
- 🌍 Complete MENA Coverage: 19 countries across Middle East and North Africa
- 🔍 Multiple Search Methods: Find by ISO code, name, dial code, or currency
- 🌐 Full Localization: Arabic and English names (common + official) with automatic locale switching
- 🏴 Advanced Flag System: SVG, PNG (emoji-style), and JPEG/PNG images
- 📐 Flexible Sizing: 24 emoji sizes + 15 image sizes (width/height based)
- 🎨 Format Options: PNG (lossless) and JPEG (compressed) support
- 📱 Zero Dependencies: Pure Dart implementation, no external packages
- 🚀 Offline First: No network calls - all data bundled with package
- 📊 JSON Ready: Built-in serialization for APIs and storage
- 🎯 Null Safe: Complete null safety for robust applications
- 📦 Lightweight: Minimal footprint, optimized performance
🚀 Quick Start #
Add to your pubspec.yaml
:
dependencies:
mena: ^1.0.1
Import and use:
import 'package:mena/mena.dart';
void main() {
// Find country by ISO code
final palestine = MENA.getBy(query: 'ps', key: MenaKeys.code);
print(palestine?.country.englishName); // "Palestine"
print(palestine?.country.arabicName); // "فلسطين"
// Search by name
final egypt = MENA.getBy(query: 'مصر', key: MenaKeys.arabicName); // Arabic search
print(egypt?.currency.code); // "EGP"
// Or search explicitly in English
final egyptEn = MENA.getBy(query: 'Egypt', key: MenaKeys.englishName);
// Find by phone code
final palestineByPhone = MENA.getBy(query: '970', key: MenaKeys.dialCode);
print(palestineByPhone?.dialCodeWithPlus); // "+970"
// Get Palestine flag URLs
print(palestine?.getSvgUrl); // SVG flag
print(palestine?.getEmojiUrl(EmojiSize.size48x36)); // 48x36 PNG
print(palestine?.getImageUrl(ImageSize.w160, ImageType.png)); // 160px PNG
}
🏴 Flag System #
MENA provides the most comprehensive flag system available for Dart packages, offering multiple formats and sizes to suit any use case:
Flag Formats #
Format | Method | Description | Best For |
---|---|---|---|
SVG | getSvgUrl |
Scalable vector graphics | High-quality displays, print |
PNG (Emoji) | getEmojiUrl(EmojiSize) |
Emoji-style flags, exact dimensions | UI icons, emoji displays |
JPEG/PNG (Image) | getImageUrl(ImageSize, ImageType) |
Flexible sizing, format choice | Web optimization, responsive design |
Available Sizes #
Emoji Sizes (PNG with exact dimensions)
24 predefined sizes maintaining 4:3 aspect ratio:
- Tiny: 16x12, 20x15, 24x18, 28x21, 32x24
- Small: 40x30, 48x36, 56x42, 64x48, 72x54
- Medium: 80x60, 96x72, 112x84, 128x96, 144x108
- Large: 160x120, 192x144, 224x168, 256x192
- Extra Large: 320x240, 384x288, 512x384, 640x480, 768x576
Image Sizes (Width/Height based)
15 flexible sizes with automatic aspect ratio:
- Width-based: w20, w40, w80, w160, w320, w640, w1280, w2560
- Height-based: h20, h24, h40, h60, h80, h120, h240
Image Types
- PNG: Lossless compression, transparency support, sharp edges
- JPEG: Lossy compression, smaller file sizes, web optimization
Usage Examples #
final palestine = MENA.getBy(query: 'ps', key: MenaKeys.code);
// SVG flag (scalable)
final svgFlag = palestine?.getSvgUrl;
// "https://flagcdn.com/ps.svg"
// Emoji-style PNG flags
final smallEmoji = palestine?.getEmojiUrl(EmojiSize.size24x18);
// "https://flagcdn.com/24x18/ps.png"
final mediumEmoji = palestine?.getEmojiUrl(EmojiSize.size48x36);
// "https://flagcdn.com/48x36/ps.png"
// Flexible image flags
final jpegFlag = palestine?.getImageUrl(ImageSize.w160);
// "https://flagcdn.com/w160/ps.jpg" (default JPEG)
final pngFlag = palestine?.getImageUrl(ImageSize.w160, ImageType.png);
// "https://flagcdn.com/w160/ps.png"
final heightFlag = palestine?.getImageUrl(ImageSize.h120, ImageType.png);
// "https://flagcdn.com/h120/ps.png"
📚 API Reference #
Search Methods #
Use a unified API with MENA.getBy(query: ..., key: MenaKeys.*)
or build an allCountriesMap(MenaKeys)
for fast lookup.
Key (MenaKeys) | Description | Example |
---|---|---|
code |
ISO 3166-1 alpha-2 code | MENA.getBy(query: 'ps', key: MenaKeys.code) |
englishName |
Common English name | MENA.getBy(query: 'Palestine', key: MenaKeys.englishName) |
arabicName |
Common Arabic name | MENA.getBy(query: 'فلسطين', key: MenaKeys.arabicName) |
dialCode |
International dial code (no '+') | MENA.getBy(query: '970', key: MenaKeys.dialCode) |
currencyCode |
ISO 4217 currency code | MENA.getBy(query: 'EGP', key: MenaKeys.currencyCode) |
officalEn / officalAr |
Official names | MENA.getBy(query: 'United Arab Emirates', key: MenaKeys.officalEn) |
capitalEn / capitalAr |
Capital city names | MENA.getBy(query: 'Abu Dhabi', key: MenaKeys.capitalEn) |
Locale Management #
Method | Description | Example |
---|---|---|
MENA.defaultLocale |
Get current locale ('ar' or 'en') | print(MENA.defaultLocale) |
MENA.setDefaultLocale(String) |
Set locale for subsequent operations | MENA.setDefaultLocale('en') |
Data Collections #
Collection | Countries | Description |
---|---|---|
MENA.allCountries |
19 | All MENA countries combined |
MENA.middleEast |
12 | Middle Eastern countries |
MENA.northernAfrica |
7 | North African countries |
Models #
MenaItemModel
class MenaItemModel {
final Country country; // Localized names & metadata (code, dialCode)
final Currency currency; // Currency data with locale-aware helpers
String get dialCodeWithPlus; // Formatted dial code, e.g., "+971"
String get getSvgUrl; // SVG flag URL
String getEmojiUrl(EmojiSize); // Emoji flag with specific dimensions
String getImageUrl(ImageSize, [ImageType]); // Flexible image with size and format
// Locale-aware convenience proxies
String get getCountryName; // Country common name (locale-aware)
String get getOfficialName; // Country official name (locale-aware)
String get getCapitalName; // Country capital (locale-aware)
String get getCurrencyName; // Currency full name (locale-aware)
String get getCurrencySymbol; // Currency symbol (locale-aware)
Map<String, dynamic> toJson();
}
Country
class Country {
final String englishName; // Common English name
final String arabicName; // Common Arabic name
final String officalEN; // Official English name
final String officalAR; // Official Arabic name
final String englishCapital; // Capital in English
final String arabicCapital; // Capital in Arabic
final String code; // ISO 3166-1 alpha-2 (e.g., "ae")
final String dialCode; // Dial code without '+' (e.g., "971")
// Note: Locale-aware getters are available in MenaItemModel
Map<String, dynamic> toJson();
}
EmojiSize
enum EmojiSize {
size16x12, size20x15, size24x18, size28x21, size32x24,
size40x30, size48x36, size56x42, size64x48, size72x54,
size80x60, size96x72, size112x84, size128x96, size144x108,
size160x120, size192x144, size224x168, size256x192,
size320x240, size384x288, size512x384, size640x480, size768x576;
String get dimensions; // e.g., "48x36"
int get width; // Calculated width
int get height; // Calculated height
double get aspectRatio; // Width/height ratio
}
ImageSize
enum ImageSize {
// Width-based
w20, w40, w80, w160, w320, w640, w1280, w2560,
// Height-based
h20, h24, h40, h60, h80, h120, h240;
String get sizeParam; // e.g., "w160" or "h120"
bool get isWidthBased; // True for width-based sizes
bool get isHeightBased; // True for height-based sizes
int get width; // Calculated width
int get height; // Calculated height
}
Currency
class Currency {
final String code; // ISO 4217 code (e.g., "ILS", "AED")
final String _enAdjective; // Country adjective (e.g., "Egyptian", "Saudi")
final String _arAdjective; // Country adjective Arabic (e.g., "مصري", "سعودي")
final CurrencyType type; // Currency type classification
String get fullEnglishName; // Full English name (e.g., "Egyptian Pound")
String get fullArabicName; // Full Arabic name (e.g., "جنيه مصري")
String get englishSymbol; // English symbol (ISO code)
String get arabicSymbol; // Arabic symbol (e.g., "₪", "د.إ")
Map<String, dynamic> toJson(); // JSON serialization
}
CurrencyType
enum CurrencyType {
dinar, riyal, dirham, pound, shekel, ouguiya;
String get englishName; // "Dinar", "Riyal", etc.
String get arabicName; // "دينار", "ريال", etc. (Arabic)
List<String> get menaCurrencies; // Currency codes using this type
}
ImageType
enum ImageType {
png, jpeg;
String get extension; // File extension
bool get supportsTransparency; // PNG supports transparency
bool get isLossless; // PNG is lossless
String get description; // Human-readable format
}
💡 Usage Examples #
Country Selector #
import 'package:mena/mena.dart';
class CountrySelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DropdownButton<MenaItemModel>(
items: MENA.allCountries.map((country) {
return DropdownMenuItem(
value: country,
child: Row(
children: [
Image.network(
country.getEmojiUrl(EmojiSize.size20x15),
width: 20,
height: 15,
),
SizedBox(width: 8),
Text(country.country.englishName),
],
),
);
}).toList(),
onChanged: (country) {
print('Selected: ${country?.country.englishName}');
},
);
}
}
Phone Number Input #
import 'package:mena/mena.dart';
class PhoneInput extends StatefulWidget {
@override
_PhoneInputState createState() => _PhoneInputState();
}
class _PhoneInputState extends State<PhoneInput> {
MenaItemModel? selectedCountry = MENA.getBy(query: 'ps', key: MenaKeys.code); // Default to Palestine
@override
Widget build(BuildContext context) {
return Row(
children: [
// Country code picker
DropdownButton<MenaItemModel>(
value: selectedCountry,
items: MENA.allCountries.map((country) {
return DropdownMenuItem(
value: country,
child: Text(country.dialCodeWithPlus),
);
}).toList(),
onChanged: (country) {
setState(() => selectedCountry = country);
},
),
SizedBox(width: 8),
// Phone number input
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: 'Phone number',
prefixText: '${selectedCountry?.dialCodeWithPlus} ',
),
keyboardType: TextInputType.phone,
),
),
],
);
}
}
Flag Gallery #
import 'package:mena/mena.dart';
class FlagGallery extends StatelessWidget {
@override
Widget build(BuildContext context) {
final palestine = MENA.getBy(query: 'ps', key: MenaKeys.code);
return Column(
children: [
// High-quality SVG flag for Palestine
Image.network(
palestine!.getSvgUrl,
width: 200,
height: 150,
),
SizedBox(height: 20),
// Different sizes for different use cases
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Small Palestine flag icon
Image.network(
palestine.getEmojiUrl(EmojiSize.size24x18),
width: 24,
height: 18,
),
// Medium Palestine flag icon
Image.network(
palestine.getEmojiUrl(EmojiSize.size48x36),
width: 48,
height: 36,
),
// Large PNG for high quality
Image.network(
palestine.getImageUrl(ImageSize.w160, ImageType.png),
width: 160,
),
// Compressed JPEG for performance
Image.network(
palestine.getImageUrl(ImageSize.w160, ImageType.jpeg),
width: 160,
),
],
),
],
);
}
}
Locale Management #
import 'package:mena/mena.dart';
void localeExamples() {
// Default locale is Arabic
print(MENA.defaultLocale); // 'ar'
final country = MENA.getBy(query: 'ae', key: MenaKeys.code);
print(country?.getCountryName); // "الإمارات" (Arabic)
print(country?.getOfficialName); // "الإمارات العربية المتحدة" (Arabic)
print(country?.getCapitalName); // "أبو ظبي" (Arabic)
// Switch to English
MENA.setDefaultLocale('en');
print(country?.getCountryName); // "United Arab Emirates" (English)
print(country?.getOfficialName); // "United Arab Emirates" (English)
print(country?.getCapitalName); // "Abu Dhabi" (English)
// Search examples with keys
final search1 = MENA.getBy(query: 'Egypt', key: MenaKeys.englishName);
MENA.setDefaultLocale('ar');
final search2 = MENA.getBy(query: 'مصر', key: MenaKeys.arabicName);
}
Currency Display #
import 'package:mena/mena.dart';
void displayPrices() {
final currencies = ['EGP', 'AED', 'SAR', 'ILS']; // Egypt first
for (final currencyCode in currencies) {
final country = MENA.getBy(query: currencyCode, key: MenaKeys.currencyCode);
if (country != null) {
print('Currency: ${country.currency.code}');
print('English: ${country.currency.fullEnglishName}');
print('Arabic: ${country.currency.fullArabicName}');
print('Localized: ${country.getCurrencyName}'); // Adapts to locale
print('Symbol: ${country.getCurrencySymbol}'); // Adapts to locale
print('Country: ${country.getCountryName}'); // Adapts to locale
print('---');
}
}
}
// Advanced currency features
void advancedCurrencyFeatures() {
final palestine = MENA.getBy(query: 'ps', key: MenaKeys.code);
if (palestine != null) {
final currency = palestine.currency;
// Display price with currency
print('Price: 100 ${currency.code}'); // "Price: 100 ILS"
print('In Arabic: ١٠٠ ${currency.fullArabicName}');
// Use symbol if available
final symbol = currency.arabicSymbol;
print('With symbol: $symbol 100'); // "With symbol: ₪ 100"
// Currency components and constructed names
print('Country adjective (EN): ${currency._enAdjective}'); // Note: private field
print('Country adjective (AR): ${currency._arAdjective}'); // Note: private field
print('Currency type (EN): ${currency.type.englishName}');
print('Currency type (AR): ${currency.type.arabicName}');
// New convenient getters
print('Full English name: ${currency.fullEnglishName}');
print('Full Arabic name: ${currency.fullArabicName}');
// Currency type analysis
print('Type: ${currency.type.englishName}');
print('Type Arabic: ${currency.type.arabicName}');
}
}
// Group currencies by type
void analyzeCurrencyTypes() {
final dinars = MENA.allCountries
.where((c) => c.currency.type == CurrencyType.dinar)
.toList();
final riyals = MENA.allCountries
.where((c) => c.currency.type == CurrencyType.riyal)
.toList();
print('Dinar countries (${dinars.length}): ${dinars.map((c) => c.country.code).join(", ")}');
print('Riyal countries (${riyals.length}): ${riyals.map((c) => c.country.code).join(", ")}');
}
API Integration #
import 'package:mena/mena.dart';
import 'dart:convert';
Future<void> sendCountryData() async {
final country = MENA.getBy(query: 'sa', key: MenaKeys.code);
if (country != null) {
// Serialize for API
final payload = {
'user_country': country.toJson(),
'currency_preference': country.currency.toJson(),
'locale': 'ar_${country.country.code.toUpperCase()}',
};
// Send to API
final jsonString = json.encode(payload);
print('API Payload: $jsonString');
}
}
🌍 Supported Countries #
Middle East (12 countries) #
🇸🇦 Saudi Arabia • 🇦🇪 United Arab Emirates • 🇰🇼 Kuwait • 🇶🇦 Qatar • 🇧🇭 Bahrain • 🇴🇲 Oman • 🇯🇴 Jordan • 🇱🇧 Lebanon • 🇵🇸 Palestine • 🇮🇶 Iraq • 🇸🇾 Syria • 🇾🇪 Yemen
North Africa (7 countries) #
🇪🇬 Egypt • 🇸🇩 Sudan • 🇱🇾 Libya • 🇹🇳 Tunisia • 🇩🇿 Algeria • 🇲🇦 Morocco • 🇲🇷 Mauritania
📱 Platform Support #
- ✅ Flutter: Android, iOS, Web, Desktop
- ✅ Dart: Server-side applications
- ✅ Web: Browser applications
- ✅ Desktop: Windows, macOS, Linux
🤝 Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links #
⭐ Support #
If this package helped you, please consider:
- ⭐ Starring the repository on GitHub
- 👍 Liking the package on pub.dev
- 🐛 Reporting issues or suggesting improvements
- 💰 Sponsoring the project
Made with ❤️ for the MENA developer community