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.
- โจ Features
- ๐ Quick Start
- ๐ด Flag System
- ๐ API Reference
- ๐ก Usage Examples
- ๐ Supported Countries
- ๐ฑ Platform Support
- ๐ค Contributing
- ๐ License
- ๐ Links
- โญ Support
- ๐ 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
Add to your pubspec.yaml:
dependencies:
mena: ^1.0.1Import 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
}MENA provides the most comprehensive flag system available for Dart packages, offering multiple formats and sizes to suit any use case:
| 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 |
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
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
- PNG: Lossless compression, transparency support, sharp edges
- JPEG: Lossy compression, smaller file sizes, web optimization
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"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) |
| 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') |
| Collection | Countries | Description |
|---|---|---|
MENA.allCountries |
19 | All MENA countries combined |
MENA.middleEast |
12 | Middle Eastern countries |
MENA.northernAfrica |
7 | North African countries |
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();
}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();
}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
}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
}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
}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
}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
}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}');
},
);
}
}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,
),
),
],
);
}
}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,
),
],
),
],
);
}
}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);
}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(", ")}');
}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');
}
}๐ธ๐ฆ Saudi Arabia โข ๐ฆ๐ช United Arab Emirates โข ๐ฐ๐ผ Kuwait โข ๐ถ๐ฆ Qatar โข ๐ง๐ญ Bahrain โข ๐ด๐ฒ Oman โข ๐ฏ๐ด Jordan โข ๐ฑ๐ง Lebanon โข ๐ต๐ธ Palestine โข ๐ฎ๐ถ Iraq โข ๐ธ๐พ Syria โข ๐พ๐ช Yemen
๐ช๐ฌ Egypt โข ๐ธ๐ฉ Sudan โข ๐ฑ๐พ Libya โข ๐น๐ณ Tunisia โข ๐ฉ๐ฟ Algeria โข ๐ฒ๐ฆ Morocco โข ๐ฒ๐ท Mauritania
- โ Flutter: Android, iOS, Web, Desktop
- โ Dart: Server-side applications
- โ Web: Browser applications
- โ Desktop: Windows, macOS, Linux
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
This project is licensed under the MIT License - see the LICENSE file for details.
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