npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arc-js/intl

v0.0.97

Published

INTL est un système de gestion d'internationalisation (i18n) modulaire et performant pour les applications React avec TypeScript/JavaScript. Il fournit une gestion avancée des traductions, un chargement dynamique des modules, et une intégration transparen

Readme

@arc-js/intl

License TypeScript React Vite

@arc-js/intl est un système de gestion d'internationalisation (i18n) modulaire et performant pour les applications React avec TypeScript/JavaScript. Il fournit une gestion avancée des traductions, un chargement dynamique des modules, et une intégration transparente avec l'écosystème Arc.

✨ Fonctionnalités Principales

🌍 Gestion Multi-Langue Avancée

  • Support de plusieurs locales avec détection automatique
  • Chargement dynamique des fichiers de traduction
  • Gestion des pluriels basée sur les règles Intl
  • Interpolation de variables dans les traductions

📦 Architecture Modulaire

  • Traductions par module avec isolation complète
  • Chargement à la demande des traductions des modules
  • Fusion intelligente des traductions hiérarchiques
  • Support des namespaces pour une organisation claire

⚡ Performance Optimisée

  • Chargement paresseux des fichiers de traduction
  • Mémoire cache des traductions chargées
  • Minimal bundle size grâce au code splitting
  • Hot reload pendant le développement

🔧 Intégration Facile

  • Provider React simple à configurer
  • Hooks personnalisés pour une utilisation intuitive
  • Compatibilité totale avec TypeScript
  • Intégration avec @arc-js/cooks pour la persistance

📦 Installation

Via npm/yarn/pnpm

npm install @arc-js/intl @arc-js/cooks react
# ou
yarn add @arc-js/intl @arc-js/cooks react
# ou
pnpm add @arc-js/intl @arc-js/cooks react

Dépendances requises

  • React 19+
  • @arc-js/cooks 1.0.0+
  • TypeScript 5.0+ (recommandé)
  • Vite (pour le chargement dynamique)

🚀 Démarrage Rapide

Structure de projet recommandée

src/
├── locales/
│   ├── en.json          # Traductions anglaises de base
│   └── fr.json          # Traductions françaises de base
├── modules/
│   ├── admin/
│   │   └── locales/
│   │       ├── en.json  # Traductions admin anglaises
│   │       └── fr.json  # Traductions admin françaises
│   └── dashboard/
│       └── locales/
│           ├── en.json  # Traductions dashboard anglaises
│           └── fr.json  # Traductions dashboard françaises
└── main.tsx

Configuration de base

// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ArcIntlProvider } from '@arc-js/intl';

const App = () => {
  return (
    <div>
      <h1>Mon Application Internationalisée</h1>
      {/* Votre contenu ici */}
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ArcIntlProvider 
      translations={{
        base: {
          en: async () => (await import('./locales/en.json')).default,
          fr: async () => (await import('./locales/fr.json')).default
        }
      }}
      supportedLocales={['en', 'fr', 'es']}
    >
      <App />
    </ArcIntlProvider>
  </React.StrictMode>
);

Fichiers de traduction

// locales/en.json
{
  "common": {
    "welcome": "Welcome to our application",
    "login": "Sign in",
    "logout": "Sign out",
    "save": "Save changes"
  },
  "errors": {
    "required": "This field is required",
    "email": "Please enter a valid email address"
  }
}

// modules/admin/locales/en.json
{
  "admin": {
    "dashboard": {
      "title": "Admin Dashboard",
      "users": "Manage Users",
      "settings": "System Settings"
    }
  }
}

📚 Documentation API

Hook useTranslation

import { useTranslation } from '@arc-js/intl';

const MyComponent = () => {
  const {
    t,                    // Fonction de traduction principale
    changeLocale,         // Changer la locale
    currentLocale,        // Locale actuelle
    isLoading             // État de chargement
  } = useTranslation('admin'); // Optionnel: nom du module

  // Exemple d'utilisation
  const handleChangeLanguage = () => {
    changeLocale(currentLocale === 'en' ? 'fr' : 'en');
  };

  return (
    <div>
      <h1>{t('admin.dashboard.title')}</h1>
      <p>{t('common.welcome')}</p>
      <button onClick={handleChangeLanguage}>
        Switch to {currentLocale === 'en' ? 'French' : 'English'}
      </button>
    </div>
  );
};

ArcIntlProvider

import { ArcIntlProvider } from '@arc-js/intl';

// Configuration complète avec modules
<ArcIntlProvider 
  translations={{
    base: {
      en: async () => (await import('./locales/en.json')).default,
      fr: async () => (await import('./locales/fr.json')).default
    },
    modules: {
      admin: {
        en: async () => (await import('./modules/admin/locales/en.json')).default,
        fr: async () => (await import('./modules/admin/locales/fr.json')).default
      },
      dashboard: {
        en: async () => (await import('./modules/dashboard/locales/en.json')).default,
        fr: async () => (await import('./modules/dashboard/locales/fr.json')).default
      }
    }
  }}
  supportedLocales={['en', 'fr', 'es']}
>
  {children}
</ArcIntlProvider>

🔧 Utilisation Avancée

Traductions avec paramètres

// locales/en.json
{
  "greeting": "Hello, {name}!",
  "items_count": "You have {count} item{count, plural, one {} other {s}}"
}

// Utilisation dans le composant
const Greeting = ({ userName, itemCount }) => {
  const { t } = useTranslation();
  
  return (
    <div>
      <p>{t('greeting', { name: userName })}</p>
      <p>{t('items_count', { count: itemCount })}</p>
    </div>
  );
};

Pluriels et contextes

// locales/en.json
{
  "messages": {
    "unread": {
      "one": "You have one unread message",
      "other": "You have {count} unread messages"
    }
  }
}

// Utilisation
const Notification = ({ unreadCount }) => {
  const { t } = useTranslation();
  
  return (
    <div>
      {/* Pluriel automatique */}
      <p>{t('messages.unread', { count: unreadCount })}</p>
    </div>
  );
};

Chargement dynamique de modules

import { useEffect } from 'react';
import { useTranslation } from '@arc-js/intl';

const AdminModule = () => {
  const { loadModule, t, isModuleLoaded } = useTranslation('admin');
  
  useEffect(() => {
    // Charger les traductions du module admin à la demande
    if (!isModuleLoaded) {
      loadModule('admin');
    }
  }, []);
  
  if (!isModuleLoaded) return <div>Loading translations...</div>;
  
  return (
    <div>
      <h1>{t('admin.dashboard.title')}</h1>
    </div>
  );
};

🎯 Exemples Complets

Exemple 1 : Sélecteur de langue

import { useTranslation } from '@arc-js/intl';

const LanguageSwitcher = () => {
  const { currentLocale, changeLocale, t } = useTranslation();
  
  const languages = [
    { code: 'en', name: 'English' },
    { code: 'fr', name: 'Français' },
    { code: 'es', name: 'Español' },
    { code: 'de', name: 'Deutsch' }
  ];
  
  return (
    <div className="language-switcher">
      <span>{t('common.language')}:</span>
      <select 
        value={currentLocale}
        onChange={(e) => changeLocale(e.target.value)}
      >
        {languages.map(lang => (
          <option key={lang.code} value={lang.code}>
            {lang.name}
          </option>
        ))}
      </select>
    </div>
  );
};

Exemple 2 : Formulaire internationalisé

import { useTranslation } from '@arc-js/intl';
import { useState } from 'react';

const ContactForm = () => {
  const { t } = useTranslation();
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: ''
  });
  
  const handleSubmit = (e) => {
    e.preventDefault();
    // Soumettre le formulaire
  };
  
  return (
    <form onSubmit={handleSubmit} className="contact-form">
      <div className="form-group">
        <label>{t('form.name')}</label>
        <input
          value={formData.name}
          onChange={e => setFormData({...formData, name: e.target.value})}
          placeholder={t('form.name_placeholder')}
        />
        {!formData.name && (
          <span className="error">{t('errors.required')}</span>
        )}
      </div>
      
      <div className="form-group">
        <label>{t('form.email')}</label>
        <input
          type="email"
          value={formData.email}
          onChange={e => setFormData({...formData, email: e.target.value})}
          placeholder={t('form.email_placeholder')}
        />
      </div>
      
      <div className="form-group">
        <label>{t('form.message')}</label>
        <textarea
          value={formData.message}
          onChange={e => setFormData({...formData, message: e.target.value})}
          placeholder={t('form.message_placeholder')}
          rows={4}
        />
      </div>
      
      <button type="submit">
        {t('form.submit')}
      </button>
    </form>
  );
};

Exemple 3 : Dashboard avec modules multiples

import { useTranslation } from '@arc-js/intl';
import { useEffect } from 'react';

const Dashboard = () => {
  const { t, loadModule, currentLocale, isLoading } = useTranslation('admin');
  
  // Charger les traductions de plusieurs modules
  useEffect(() => {
    const loadModules = async () => {
      await loadModule('admin');
      await loadModule('analytics');
      await loadModule('reports');
    };
    loadModules();
  }, [currentLocale]);
  
  if (isLoading) return <div>Loading translations...</div>;
  
  return (
    <div className="dashboard">
      <header>
        <h1>{t('admin.dashboard.title')}</h1>
        <p>{t('common.welcome', { user: 'John Doe' })}</p>
      </header>
      
      <section className="stats">
        <div className="stat-card">
          <h3>{t('analytics.visitors', {}, { moduleName: 'analytics' })}</h3>
          <p>1,234</p>
        </div>
        
        <div className="stat-card">
          <h3>{t('reports.monthly', {}, { moduleName: 'reports' })}</h3>
          <p>{t('reports.growth', { percent: '15%' })}</p>
        </div>
      </section>
      
      <footer>
        <p>{t('common.last_updated', { date: new Date().toLocaleDateString(currentLocale) })}</p>
      </footer>
    </div>
  );
};

📋 API Reference

ArcIntlProvider

| Prop | Type | Description | Required | |------|------|-------------|----------| | translations | TranslationsConfig | Configuration des chargeurs de traductions | Oui | | supportedLocales | string[] | Locales supportées (défaut: ['en', 'fr']) | Non | | children | React.ReactNode | Composants enfants | Oui |

Hook useTranslation

Retourne un objet avec:

  • t(key: string, params?: Record<string, any>, options?: TranslationOptions): Fonction de traduction
  • changeLocale(locale: string): Changer la locale actuelle
  • currentLocale: Locale actuelle
  • isLoading: État de chargement global
  • isModuleLoaded: Indique si le module demandé est chargé
  • loadModule(moduleName: string): Charge un module spécifique

Options de Traduction

interface TranslationOptions {
  moduleName?: string;      // Nom du module (défaut: 'core')
  defaultValue?: string;    // Valeur par défaut si clé non trouvée
  count?: number;          // Pour la gestion des pluriels
  context?: string;        // Contexte spécifique
}

Structure de configuration

interface TranslationsConfig {
  base: {
    [locale: string]: () => Promise<Record<string, any>>;
  };
  modules?: {
    [moduleName: string]: {
      [locale: string]: () => Promise<Record<string, any>>;
    };
  };
}

🛡️ Gestion des Erreurs

Fallback sécurisé

const SafeComponent = () => {
  const { t } = useTranslation();
  
  // Utilisation sécurisée avec valeur par défaut
  const title = t('nonexistent.key', {}, { 
    defaultValue: 'Default Title' 
  });
  
  // Si pas de valeur par défaut, retourne la clé
  const subtitle = t('another.missing.key'); // Retourne: "another.missing.key"
  
  return (
    <div>
      <h1>{title}</h1>
      <p>{subtitle}</p>
    </div>
  );
};

Logs en développement

// En mode développement, les clés manquantes sont automatiquement loggées
const MissingTranslations = () => {
  const { t } = useTranslation();
  
  // Ceci loggue un avertissement en développement
  const missingKey = t('non.existent.key');
  
  return <div>{missingKey}</div>;
};

🔧 Configuration TypeScript

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "DOM.Iterable", "ES2020"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "types": ["vite/client"]
  },
  "include": ["src", "node_modules/@arc-js/intl/**/*"]
}

📋 Table des Conventions

Structure des fichiers JSON

| Chemin | Description | Exemple | |--------|-------------|---------| | locales/{locale}.json | Traductions de base | locales/en.json | | modules/{module}/locales/{locale}.json | Traductions du module | modules/admin/locales/fr.json | | public/locales/{locale}.json | Traductions statiques (optionnel) | public/locales/es.json |

Clés de traduction

| Format | Description | Exemple | |--------|-------------|---------| | namespace.key | Clé simple | common.save | | namespace.nested.key | Clé imbriquée | form.contact.email | | key_{context} | Avec contexte | save_draft, save_final |

Paramètres supportés

| Paramètre | Type | Description | |-----------|------|-------------| | count | number | Pour la gestion des pluriels | | context | string | Contexte spécifique (draft, final, etc.) | | moduleName | string | Module cible pour la traduction | | defaultValue | string | Valeur par défaut si la clé n'existe pas |

🔧 Build et Développement

Scripts recommandés

{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "type-check": "tsc --noEmit",
    "extract-translations": "node scripts/extract-keys.js",
    "validate-translations": "node scripts/validate-translations.js"
  }
}

Configuration Vite

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@arc-js/intl': '@arc-js/intl/index.js'
    }
  }
});

📄 Licence

MIT License - Voir le fichier LICENSE pour plus de détails.

🐛 Signaler un Bug

Envoyez-nous un mail à l'adresse [email protected] pour :

  • Signaler un bug
  • Proposer une amélioration
  • Poser une question sur l'utilisation
  • Demander une nouvelle fonctionnalité

@arc-js/intl - La solution d'internationalisation modulaire pour React et TypeScript.

Développé par l'équipe INICODE