@je-es/client 0.1.7 → 0.1.9

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 CHANGED
@@ -8,11 +8,11 @@
8
8
  </div>
9
9
 
10
10
  <div align="center">
11
- <img src="https://img.shields.io/badge/v-0.1.7-black"/>
11
+ <img src="https://img.shields.io/badge/v-0.1.9-black"/>
12
12
  <img src="https://img.shields.io/badge/🔥-@je--es-black"/>
13
13
  <br>
14
14
  <img src="https://github.com/je-es/client/actions/workflows/ci.yml/badge.svg" alt="CI" />
15
- <img src="https://img.shields.io/badge/coverage-90%25-brightgreen" alt="Test Coverage" />
15
+ <!-- <img src="https://img.shields.io/badge/coverage-70%25-brightgreen" alt="Test Coverage" /> -->
16
16
  <img src="https://img.shields.io/github/issues/je-es/client?style=flat" alt="Github Repo Issues" />
17
17
  <img src="https://img.shields.io/github/stars/je-es/client?style=social" alt="GitHub Repo stars" />
18
18
  </div>
@@ -143,6 +143,8 @@
143
143
  }
144
144
  ```
145
145
 
146
+ > **_Components that manage their own DOM directly (like Notifications and ItemsLoader) shouldn't use @state decorators for properties that trigger re-renders. The @state decorator is designed for components that rely on virtual DOM patching. When you manage DOM directly with appendChild/remove, re-renders destroy your manual DOM changes._**
147
+
146
148
  <div align="center"> <img src="./assets/img/line.png" alt="line" style="display: block; margin-top:20px;margin-bottom:20px;width:500px;"/> <br> </div>
147
149
 
148
150
  - ### SCSS Styling System
@@ -413,6 +415,153 @@
413
415
 
414
416
  <div align="center"> <img src="./assets/img/line.png" alt="line" style="display: block; margin-top:20px;margin-bottom:20px;width:500px;"/> <br> </div>
415
417
 
418
+ - ### Internationalization (i18n)
419
+
420
+ **Setup in App Initialization:**
421
+
422
+ ```typescript
423
+ import { setupI18n, t } from '@je-es/client';
424
+
425
+ // In your app initialization (browser.ts or similar)
426
+ async function initializeApp() {
427
+ // 1. Setup i18n - loads the currently selected language
428
+ // (from localStorage if user visited before, otherwise default)
429
+ await setupI18n({
430
+ defaultLanguage: 'en',
431
+ supportedLanguages: ['en', 'ar'],
432
+ staticPath: 'static/i18n'
433
+ });
434
+
435
+ // 2. Now safe to use t() and render components
436
+ const app = new MyApp();
437
+ await app.init();
438
+ }
439
+
440
+ // Call when DOM is ready
441
+ if (document.readyState === 'loading') {
442
+ document.addEventListener('DOMContentLoaded', initializeApp);
443
+ } else {
444
+ initializeApp();
445
+ }
446
+ ```
447
+
448
+ **Use `t()` Anywhere:**
449
+
450
+ ```typescript
451
+ import { t, setLanguage, loadLanguageFile, getCurrentLanguage } from '@je-es/client';
452
+
453
+ // After setupI18n() resolves, you can use t() directly everywhere!
454
+ console.log(t('hello')); // Works in current language!
455
+ console.log(t('welcome', { app_name: 'MyApp' }));
456
+
457
+ // Switch language with lazy-loading (loads file only when needed)
458
+ async function selectLanguage(lang: string) {
459
+ await loadLanguageFile(lang); // Load language on-demand
460
+ setLanguage(lang);
461
+ console.log(getCurrentLanguage()); // New language
462
+ }
463
+ ```
464
+
465
+ **Lazy-Loading Languages for Performance:**
466
+
467
+ `setupI18n()` loads the **currently selected language** on page load:
468
+ - **First visit**: Loads default language (e.g., en.json)
469
+ - **After switching**: Loads new language on-demand
470
+ - **Returning user**: Loads their previously selected language from localStorage
471
+
472
+ ```typescript
473
+ // Returning user who previously selected Arabic
474
+ // Page loads with ar.json (their choice) - fast! ⚡
475
+ await setupI18n({
476
+ defaultLanguage: 'en',
477
+ supportedLanguages: ['en', 'ar', 'fr'],
478
+ staticPath: 'static/i18n'
479
+ });
480
+
481
+ // User clicks to switch language
482
+ await loadLanguageFile('fr'); // Load only when needed
483
+ setLanguage('fr');
484
+ ```
485
+
486
+ **In Components:**
487
+
488
+ ```typescript
489
+ import { Component, html } from '@je-es/client';
490
+ import { t, setLanguage, loadLanguageFile, createTranslator } from '@je-es/client';
491
+
492
+ class MultiLanguageComponent extends Component {
493
+ render() {
494
+ return html`
495
+ <div>
496
+ <h1>${t('welcome', { app_name: 'JE-ES' })}</h1>
497
+ <button onclick=${() => this.switchLang('en')}>
498
+ English
499
+ </button>
500
+ <button onclick=${() => this.switchLang('ar')}>
501
+ العربية
502
+ </button>
503
+ </div>
504
+ `;
505
+ }
506
+
507
+ async switchLang(lang: string) {
508
+ await loadLanguageFile(lang);
509
+ setLanguage(lang);
510
+ this.refresh();
511
+ }
512
+
513
+ connectedCallback() {
514
+ super.connectedCallback();
515
+ // Subscribe to language changes
516
+ this.unsubscribe = createTranslator(() => this.refresh());
517
+ }
518
+
519
+ disconnectedCallback() {
520
+ super.disconnectedCallback();
521
+ if (this.unsubscribe) {
522
+ this.unsubscribe();
523
+ }
524
+ }
525
+ }
526
+ ```
527
+
528
+ **Advanced Usage:**
529
+
530
+ ```typescript
531
+ import { t, tLang, loadLanguage, getSupportedLanguages, hasKey } from '@je-es/client';
532
+
533
+ // Translate with specific language temporarily
534
+ console.log(t('hello')); // Current language
535
+ console.log(tLang('hello', 'en')); // Temporarily use English
536
+
537
+ // Load specific language dynamically
538
+ loadLanguage('fr', {
539
+ hello: 'Bonjour',
540
+ welcome: 'Bienvenue dans {app_name}'
541
+ });
542
+
543
+ // Check supported languages
544
+ console.log(getSupportedLanguages()); // ['en', 'ar', 'fr']
545
+
546
+ // Check if key exists
547
+ if (hasKey('custom_key')) {
548
+ console.log(t('custom_key'));
549
+ }
550
+ ```
551
+
552
+ > **_Features:_**
553
+ > - **Lazy-loaded languages**: Default language loads on init, others load on-demand
554
+ > - **Fast page load**: Only default language file is downloaded initially
555
+ > - **localStorage support**: Automatically saves language preference
556
+ > - **Parameter replacement**: Replace placeholders with dynamic values
557
+ > - **Nested translations**: Use translation keys as parameter values
558
+ > - **Reactive updates**: Listen to language changes with `createTranslator()`
559
+ > - **Fallback language**: Falls back to configured default language if translation is missing
560
+ > - **Multiple languages**: Support for unlimited languages
561
+ > - **URL loading**: Load translations from remote JSON files or manually with `loadLanguageFile()`
562
+
563
+ <div align="center"> <img src="./assets/img/line.png" alt="line" style="display: block; margin-top:20px;margin-bottom:20px;width:500px;"/> <br> </div>
564
+
416
565
  - ### API Integration
417
566
 
418
567
  ```typescript
@@ -514,6 +663,8 @@
514
663
  }
515
664
  ```
516
665
 
666
+ > **_Note:_** i18n is now configured directly in your app initialization via `setupI18n()` instead of in the client config. See the [Internationalization section](#internationalization-i18n) for details.
667
+
517
668
  <div align="center"> <img src="./assets/img/line.png" alt="line" style="display: block; margin-top:20px;margin-bottom:20px;width:500px;"/> <br> </div>
518
669
 
519
670
  - ### Build Commands