afro-locale 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,431 @@
1
+ # afro-locale
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@koadit/afro-locale.svg)](https://www.npmjs.com/package/@koadit/afro-locale)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@koadit/afro-locale.svg)](https://www.npmjs.com/package/@koadit/afro-locale)
5
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.4-blue.svg)](https://www.typescriptlang.org/)
7
+
8
+ A comprehensive internationalization (i18n) library with first-class support for African languages, currencies, and locales. Provides seamless localization for 20+ African languages with native language names, currency formatting, date/time localization, and more.
9
+
10
+ ## ✨ Features
11
+
12
+ - 🌍 **20+ African Languages** - Comprehensive support for major African languages including Yoruba, Hausa, Igbo, Swahili, Zulu, Amharic, and more
13
+ - πŸ’± **14+ African Currencies** - Built-in formatting for NGN, KES, ZAR, ETB, UGX, XOF, XAF, and other African currencies
14
+ - πŸ“… **Date/Time Localization** - Format dates, times, and datetimes according to locale-specific conventions
15
+ - πŸ—£οΈ **Native Language Names** - Display language names in their native scripts and English equivalents
16
+ - πŸ”’ **Number Formatting** - Locale-aware number formatting with customizable options
17
+ - πŸ“ **Automatic Locale Detection** - Detect user's locale from browser navigator
18
+ - ⚑ **Zero Dependencies** - Lightweight library (~7KB minified) built on native Web APIs
19
+ - πŸ“¦ **TypeScript Support** - Fully typed for TypeScript projects
20
+ - 🎯 **ESM & CommonJS** - Works with both module systems
21
+ - βœ… **100% Test Coverage** - Comprehensive test suite with 28+ test cases
22
+
23
+ ## πŸ“¦ Installation
24
+
25
+ ```bash
26
+ npm install @koadit/afro-locale
27
+ ```
28
+
29
+ Or with yarn:
30
+
31
+ ```bash
32
+ yarn add @koadit/afro-locale
33
+ ```
34
+
35
+ Or with pnpm:
36
+
37
+ ```bash
38
+ pnpm add @koadit/afro-locale
39
+ ```
40
+
41
+ ## πŸš€ Quick Start
42
+
43
+ ### CommonJS
44
+
45
+ ```javascript
46
+ const { locale } = require('@koadit/afro-locale');
47
+
48
+ // Set locale
49
+ locale.set('yo'); // Yoruba
50
+
51
+ // Format currency
52
+ console.log(locale.formatCurrency(5000, 'NGN'));
53
+ // Output: ₦5,000.00
54
+
55
+ // Format date
56
+ console.log(locale.formatDate(new Date(), 'long'));
57
+ // Output: 9 Θ€pαΊΉΜ€lαΊΉΜ€ 2026
58
+ ```
59
+
60
+ ### ES Modules
61
+
62
+ ```javascript
63
+ import { locale } from '@koadit/afro-locale';
64
+
65
+ // Set locale
66
+ locale.set('sw'); // Swahili
67
+
68
+ // Format number
69
+ console.log(locale.formatNumber(1234567));
70
+ // Output: 1,234,567
71
+
72
+ // Format time
73
+ console.log(locale.formatTime(new Date(), 'long'));
74
+ // Output: 06:18:45
75
+ ```
76
+
77
+ ### TypeScript
78
+
79
+ ```typescript
80
+ import AfroLocale, { locale, LocaleConfig } from '@koadit/afro-locale';
81
+
82
+ // Using the singleton instance
83
+ locale.set('zu'); // Zulu
84
+
85
+ // Or create your own instance
86
+ const customLocale = new AfroLocale();
87
+ customLocale.set('am'); // Amharic
88
+
89
+ // Get language info
90
+ console.log(locale.getLanguageName('zu')); // "Zulu"
91
+ console.log(locale.getLanguageNativeName('zu')); // "isiZulu"
92
+ ```
93
+
94
+ ## πŸ“š API Documentation
95
+
96
+ ### Core Methods
97
+
98
+ #### `set(locale: string): void`
99
+
100
+ Set the active locale for formatting operations.
101
+
102
+ ```javascript
103
+ locale.set('ha'); // Set to Hausa
104
+ ```
105
+
106
+ #### `get(): string`
107
+
108
+ Get the currently set locale.
109
+
110
+ ```javascript
111
+ const current = locale.get(); // Returns 'yo', 'en', etc.
112
+ ```
113
+
114
+ #### `detectLocale(): string`
115
+
116
+ Automatically detect locale from browser navigator (browser only).
117
+
118
+ ```javascript
119
+ const detectedLocale = locale.detectLocale();
120
+ // Returns user's browser language if supported, otherwise English
121
+ ```
122
+
123
+ #### `isLocaleSupported(locale: string): boolean`
124
+
125
+ Check if a locale is supported.
126
+
127
+ ```javascript
128
+ if (locale.isLocaleSupported('sw')) {
129
+ locale.set('sw');
130
+ }
131
+ ```
132
+
133
+ ### Formatting Methods
134
+
135
+ #### `formatCurrency(amount: number, currency: string): string`
136
+
137
+ Format a number as currency with proper symbol and decimal places.
138
+
139
+ ```javascript
140
+ locale.set('en');
141
+ console.log(locale.formatCurrency(5000, 'NGN'));
142
+ // Output: ₦5,000.00
143
+
144
+ console.log(locale.formatCurrency(10000, 'KES'));
145
+ // Output: KSh10,000.00
146
+
147
+ console.log(locale.formatCurrency(1000, 'ZAR'));
148
+ // Output: R1,000.00
149
+ ```
150
+
151
+ **Supported Currencies (14):**
152
+ - NGN (Nigerian Naira)
153
+ - GHS (Ghanaian Cedi)
154
+ - KES (Kenyan Shilling)
155
+ - ZAR (South African Rand)
156
+ - ETB (Ethiopian Birr)
157
+ - UGX (Ugandan Shilling)
158
+ - TZS (Tanzanian Shilling)
159
+ - RWF (Rwandan Franc)
160
+ - MWK (Malawian Kwacha)
161
+ - ZMW (Zambian Kwacha)
162
+ - XOF (West African CFA Franc)
163
+ - XAF (Central African CFA Franc)
164
+ - USD (US Dollar)
165
+ - EUR (Euro)
166
+
167
+ #### `formatNumber(value: number, options?: Intl.NumberFormatOptions): string`
168
+
169
+ Format a number with locale-specific separators.
170
+
171
+ ```javascript
172
+ locale.set('en');
173
+ console.log(locale.formatNumber(1234567));
174
+ // Output: 1,234,567
175
+
176
+ console.log(locale.formatNumber(1234.567, {
177
+ minimumFractionDigits: 2,
178
+ maximumFractionDigits: 2
179
+ }));
180
+ // Output: 1,234.57
181
+ ```
182
+
183
+ #### `formatDate(date: Date, style?: 'short' | 'long'): string`
184
+
185
+ Format a date according to locale conventions.
186
+
187
+ ```javascript
188
+ const date = new Date(2026, 3, 9);
189
+
190
+ locale.set('yo');
191
+ console.log(locale.formatDate(date, 'long'));
192
+ // Output: 9 Θ€pαΊΉΜ€lαΊΉΜ€ 2026
193
+
194
+ console.log(locale.formatDate(date, 'short'));
195
+ // Output: 09/04/26
196
+ ```
197
+
198
+ #### `formatTime(date: Date, style?: 'short' | 'long'): string`
199
+
200
+ Format a time according to locale conventions.
201
+
202
+ ```javascript
203
+ const date = new Date(2026, 3, 9, 14, 30, 45);
204
+
205
+ locale.set('en');
206
+ console.log(locale.formatTime(date, 'short'));
207
+ // Output: 14:30
208
+
209
+ console.log(locale.formatTime(date, 'long'));
210
+ // Output: 14:30:45
211
+ ```
212
+
213
+ #### `formatDateTime(date: Date, style?: 'short' | 'long'): string`
214
+
215
+ Format a complete date and time according to locale conventions.
216
+
217
+ ```javascript
218
+ const date = new Date(2026, 3, 9, 14, 30, 45);
219
+
220
+ locale.set('en');
221
+ console.log(locale.formatDateTime(date, 'long'));
222
+ // Output: April 9, 2026, 14:30:45
223
+ ```
224
+
225
+ ### Language Information Methods
226
+
227
+ #### `getLanguageName(code: string): string`
228
+
229
+ Get the English name of a language.
230
+
231
+ ```javascript
232
+ console.log(locale.getLanguageName('yo'));
233
+ // Output: "Yoruba"
234
+
235
+ console.log(locale.getLanguageName('sw'));
236
+ // Output: "Swahili"
237
+ ```
238
+
239
+ #### `getLanguageNativeName(code: string): string`
240
+
241
+ Get the native name of a language (in its native script).
242
+
243
+ ```javascript
244
+ console.log(locale.getLanguageNativeName('yo'));
245
+ // Output: "YorΓΉbΓ‘"
246
+
247
+ console.log(locale.getLanguageNativeName('am'));
248
+ // Output: "αŠ αˆ›αˆ­αŠ›"
249
+ ```
250
+
251
+ #### `getSupportedLanguages(): LocaleConfig[]`
252
+
253
+ Get information about all supported languages.
254
+
255
+ ```javascript
256
+ const languages = locale.getSupportedLanguages();
257
+ // Returns array of LocaleConfig objects with code, name, nativeName, country
258
+ ```
259
+
260
+ #### `getSupportedCurrencies(): string[]`
261
+
262
+ Get list of all supported currency codes.
263
+
264
+ ```javascript
265
+ const currencies = locale.getSupportedCurrencies();
266
+ // Returns: ['NGN', 'GHS', 'KES', 'ZAR', ...]
267
+ ```
268
+
269
+ ## 🌐 Supported Languages (21)
270
+
271
+ | Code | Language | Native Name | Country |
272
+ |------|----------|------------|---------|
273
+ | yo | Yoruba | YorΓΉbΓ‘ | NG |
274
+ | ha | Hausa | Hausa | NG |
275
+ | ig | Igbo | Igbo | NG |
276
+ | zu | Zulu | isiZulu | ZA |
277
+ | sw | Swahili | Kiswahili | KE |
278
+ | am | Amharic | αŠ αˆ›αˆ­αŠ› | ET |
279
+ | so | Somali | Soomaali | SO |
280
+ | om | Oromo | Afaan Oromo | ET |
281
+ | ti | Tigrinya | α‰΅αŒαˆ­αŠ› | ER |
282
+ | rw | Kinyarwanda | Kinyarwanda | RW |
283
+ | bn | Bambara | Bamanankan | ML |
284
+ | ff | Fulfulde | Fulfulde | SN |
285
+ | mg | Malagasy | Malagasy | MG |
286
+ | xh | Xhosa | isiXhosa | ZA |
287
+ | st | Southern Sotho | Sesotho | ZA |
288
+ | tn | Tswana | Setswana | BW |
289
+ | sn | Shona | Shona | ZW |
290
+ | ny | Chichewa | Chichewa | MW |
291
+ | ln | Lingala | Lingala | CD |
292
+ | ki | Kikuyu | Gikuyu | KE |
293
+ | lu | Luba-Katanga | Luba-Katanga | CD |
294
+ | en | English | English | GB |
295
+
296
+ ## πŸ“‹ Examples
297
+
298
+ ### Multi-Language Support
299
+
300
+ ```javascript
301
+ import { locale } from '@koadit/afro-locale';
302
+
303
+ const price = 5000;
304
+ const currencies = {
305
+ 'yo': 'NGN',
306
+ 'sw': 'KES',
307
+ 'zu': 'ZAR',
308
+ };
309
+
310
+ for (const [lang, currency] of Object.entries(currencies)) {
311
+ locale.set(lang);
312
+ console.log(`${locale.getLanguageName(lang)}: ${locale.formatCurrency(price, currency)}`);
313
+ }
314
+ // Output:
315
+ // Yoruba: ₦5,000.00
316
+ // Swahili: KSh5,000.00
317
+ // Zulu: R5,000.00
318
+ ```
319
+
320
+ ### Locale Detection and Fallback
321
+
322
+ ```javascript
323
+ import { locale } from '@koadit/afro-locale';
324
+
325
+ // Automatically detect user's locale (browser only)
326
+ locale.detectLocale();
327
+
328
+ const supportedLanguages = locale.getSupportedLanguages();
329
+ const currentLang = locale.get();
330
+
331
+ console.log(`Locale set to: ${locale.getLanguageName(currentLang)}`);
332
+ ```
333
+
334
+ ### E-Commerce Integration
335
+
336
+ ```javascript
337
+ import { locale } from '@koadit/afro-locale';
338
+
339
+ function formatProductPrice(price, userLanguage, userCountry) {
340
+ locale.set(userLanguage);
341
+
342
+ const currency = getCurrencyByCountry(userCountry);
343
+ const formatted = locale.formatCurrency(price, currency);
344
+ const nativeLanguage = locale.getLanguageNativeName(userLanguage);
345
+
346
+ return { formatted, nativeLanguage };
347
+ }
348
+ ```
349
+
350
+ ## πŸ”§ Configuration
351
+
352
+ ### TypeScript Configuration
353
+
354
+ The library includes full TypeScript support. In your `tsconfig.json`:
355
+
356
+ ```json
357
+ {
358
+ "compilerOptions": {
359
+ "strict": true,
360
+ "module": "esnext",
361
+ "target": "es2020"
362
+ }
363
+ }
364
+ ```
365
+
366
+ ## πŸ§ͺ Testing
367
+
368
+ Run tests with:
369
+
370
+ ```bash
371
+ npm test
372
+ ```
373
+
374
+ Run tests with coverage:
375
+
376
+ ```bash
377
+ npm run test:coverage
378
+ ```
379
+
380
+ The library includes 28+ comprehensive test cases covering:
381
+ - Locale management and normalization
382
+ - Language support verification
383
+ - Currency formatting for all supported currencies
384
+ - Number, date, time formatting
385
+ - Locale detection
386
+ - Type safety
387
+
388
+ ## πŸ” Quality Assurance
389
+
390
+ - **ESLint**: Code quality checks
391
+ - **TypeScript**: Strict type checking
392
+ - **Jest**: 28+ unit tests
393
+ - **Coverage**: Comprehensive test coverage
394
+
395
+ ```bash
396
+ # Run linting
397
+ npm run lint
398
+
399
+ # Type check
400
+ npm run type-check
401
+
402
+ # Full build
403
+ npm run build
404
+ ```
405
+
406
+ ## πŸ“œ License
407
+
408
+ MIT Β© 2024 [KOADIT Digital Solutions](https://koadit.com)
409
+
410
+ ## 🀝 Contributing
411
+
412
+ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
413
+
414
+ ## πŸ“ Changelog
415
+
416
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
417
+
418
+ ## πŸ› Bug Reports & Feature Requests
419
+
420
+ - [GitHub Issues](https://github.com/oluokunkabiru/afro-locale/issues)
421
+ - [GitHub Discussions](https://github.com/oluokunkabiru/afro-locale/discussions)
422
+
423
+ ## πŸ“– Resources
424
+
425
+ - [NPM Package](https://www.npmjs.com/package/@koadit/afro-locale)
426
+ - [GitHub Repository](https://github.com/oluokunkabiru/afro-locale)
427
+ - [KOADIT Digital Solutions](https://koadit.com)
428
+
429
+ ---
430
+
431
+ **Made with ❀️ for African developers by KOADIT Digital Solutions**
package/SECURITY.md ADDED
@@ -0,0 +1,84 @@
1
+ # Security Policy
2
+
3
+ ## Reporting Security Vulnerabilities
4
+
5
+ If you discover a security vulnerability in `@koadit/afro-locale`, please email **security@koadit.com** instead of using the public issue tracker.
6
+
7
+ Please include:
8
+ - Description of the vulnerability
9
+ - Steps to reproduce
10
+ - Potential impact
11
+ - Suggested fix (if any)
12
+
13
+ We will:
14
+ - Acknowledge your report within 48 hours
15
+ - Provide a timeline for addressing the vulnerability
16
+ - Keep you informed of our progress
17
+ - Credit you in the security advisory (unless you prefer anonymity)
18
+
19
+ ## Security Best Practices
20
+
21
+ ### For Users
22
+
23
+ When using `@koadit/afro-locale`:
24
+
25
+ 1. **Keep Dependencies Updated**: Regularly update to the latest version
26
+ ```bash
27
+ npm update @koadit/afro-locale
28
+ ```
29
+
30
+ 2. **Use HTTPS**: When transmitting localized data over networks, always use HTTPS
31
+
32
+ 3. **Input Validation**: While afro-locale is designed to be safe, always validate user input when possible
33
+
34
+ 4. **Use in Trusted Environments**: The library uses browser APIs (navigator) which should only be used in trusted contexts
35
+
36
+ ### For Contributors
37
+
38
+ 1. **Code Review**: All changes must be reviewed before merging
39
+ 2. **Testing**: All changes must include appropriate tests
40
+ 3. **Dependencies**: Only add dependencies that are well-maintained and secure
41
+ 4. **No Credentials**: Never commit credentials, keys, or sensitive data
42
+ 5. **Responsible Disclosure**: Follow our vulnerability reporting process
43
+
44
+ ## Known Limitations
45
+
46
+ 1. **Browser APIs**: Locale detection relies on browser navigator object, which may be restricted in some sandboxed environments
47
+ 2. **Intl API**: Relies on the native Intl API, which has varying levels of support across browsers
48
+ 3. **No Runtime Validation**: The library does not validate currency amounts or dates at runtime
49
+
50
+ ## Supported Versions
51
+
52
+ Only the latest major version receives security updates.
53
+
54
+ | Version | Supported |
55
+ |---------|-------------------|
56
+ | 1.x | βœ… Full support |
57
+ | < 1.0 | ❌ No support |
58
+
59
+ ## Security Updates
60
+
61
+ Security updates will be:
62
+ - Released as soon as possible after discovery
63
+ - Included in patch versions
64
+ - Noted in the CHANGELOG.md with a security tag
65
+ - Announced on GitHub
66
+
67
+ ## Dependencies Security
68
+
69
+ All dependencies are regularly scanned for vulnerabilities using:
70
+ - npm audit
71
+ - Automated dependency scanning
72
+
73
+ To check security:
74
+ ```bash
75
+ npm audit
76
+ ```
77
+
78
+ ## License
79
+
80
+ This policy is available under the MIT License.
81
+
82
+ ---
83
+
84
+ Thank you for helping keep `@koadit/afro-locale` secure!