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

@astacinco/rn-i18n

v0.1.0

Published

Internationalization with adapter pattern - swap i18n providers without code changes

Downloads

102

Readme

@astacinco/rn-i18n

Internationalization with adapter pattern for React Native - swap i18n providers without code changes.

Features

  • Adapter Pattern - Swap i18n providers (react-i18next, react-intl, etc.) without changing app code
  • Built-in Adapters - ReactI18next, Console (debug), NoOp (testing)
  • Translation - Key-based translation with interpolation and pluralization
  • Formatting - Date, number, currency, and percentage formatting
  • RTL Support - Automatic RTL detection for Arabic, Hebrew, etc.
  • Accessibility - Screen reader announcements and a11y settings
  • TypeScript - Full type safety with comprehensive interfaces

Installation

npm install @astacinco/rn-i18n

For react-i18next (recommended for production)

npm install i18next react-i18next

Quick Start

1. Choose your adapter

import {
  I18nProvider,
  ReactI18nextAdapter,
  ConsoleAdapter,
  NoOpAdapter,
} from '@astacinco/rn-i18n';

// Production: react-i18next
const adapter = new ReactI18nextAdapter({ i18n: i18nextInstance });

// Development: Console logging
const adapter = new ConsoleAdapter({
  defaultLocale: 'en',
  resources: translations,
});

// Testing: No-op (silent)
const adapter = new NoOpAdapter();

2. Wrap your app

function App() {
  const adapter = new ConsoleAdapter({
    defaultLocale: 'en-US',
    resources: {
      'en-US': {
        common: {
          welcome: 'Welcome, {{name}}!',
          items: { one: '1 item', other: '{{count}} items' },
        },
      },
      'es-ES': {
        common: {
          welcome: '¡Bienvenido, {{name}}!',
          items: { one: '1 artículo', other: '{{count}} artículos' },
        },
      },
    },
    supportedLocales: ['en-US', 'es-ES'],
  });

  return (
    <I18nProvider adapter={adapter} config={{ debug: __DEV__ }}>
      <MyApp />
    </I18nProvider>
  );
}

3. Use in components

import { useTranslation, useLocale, useAccessibility } from '@astacinco/rn-i18n';

function HomeScreen() {
  // Translation
  const { t, tp } = useTranslation();

  // Locale & formatting
  const { locale, isRTL, formatCurrency, setLocale } = useLocale();

  // Accessibility
  const { announce, isScreenReaderEnabled } = useAccessibility();

  return (
    <View style={{ direction: isRTL ? 'rtl' : 'ltr' }}>
      <Text>{t('common.welcome', { name: 'John' })}</Text>
      <Text>{tp('common.items', 5)}</Text>
      <Text>{formatCurrency(99.99, 'USD')}</Text>

      <Button
        title="Switch to Spanish"
        onPress={() => setLocale('es-ES')}
      />
    </View>
  );
}

API Reference

I18nProvider

Provider component that wraps your app with i18n context.

<I18nProvider
  adapter={adapter}        // Required: I18n adapter
  config={{
    defaultLocale: 'en',   // Default locale
    fallbackLocale: 'en',  // Fallback when translation missing
    debug: false,          // Enable debug logging
    logMissingTranslations: false,  // Warn on missing keys
    onMissingTranslation: (key, locale) => string, // Custom handler
  }}
>
  {children}
</I18nProvider>

Built-in Adapters

ConsoleAdapter (Development)

import { ConsoleAdapter } from '@astacinco/rn-i18n';

const adapter = new ConsoleAdapter({
  prefix: '[I18n]',        // Log prefix
  timestamps: true,        // Include timestamps
  defaultLocale: 'en',     // Initial locale
  resources: {             // Translation resources
    en: {
      common: {
        hello: 'Hello',
        greeting: 'Hello, {{name}}!',
        items: { one: '1 item', other: '{{count}} items' },
      },
    },
  },
  supportedLocales: ['en', 'es', 'fr'],
});

NoOpAdapter (Testing)

import { NoOpAdapter } from '@astacinco/rn-i18n';

const adapter = new NoOpAdapter();
// Returns keys as-is, useful for testing

ReactI18nextAdapter (Production)

import { ReactI18nextAdapter } from '@astacinco/rn-i18n';
import i18n from './i18n'; // Your i18next instance

const adapter = new ReactI18nextAdapter({
  i18n,
  supportedLocales: ['en', 'es', 'fr'],
});

Creating Custom Adapters

Implement the I18nAdapter interface:

import type { I18nAdapter } from '@astacinco/rn-i18n';

class MyCustomAdapter implements I18nAdapter {
  readonly name = 'custom';

  async initialize() {
    // Initialize your i18n library
  }

  translate(key: string, params?: TranslationParams): string {
    // Return translated string
  }

  translatePlural(key: string, count: number, params?: TranslationParams): string {
    // Return plural-aware translation
  }

  // ... implement all other methods
}

Hooks

useTranslation

Main hook for translations.

const {
  t,          // Translate key: t('common.hello')
  tp,         // Translate plural: tp('items', 5)
  hasKey,     // Check key exists: hasKey('common.hello')
  locale,     // Current locale
  language,   // Current language code
  isReady,    // Provider initialized
} = useTranslation({
  keyPrefix: 'profile',           // Optional: prefix all keys
  defaultParams: { app: 'MyApp' }, // Optional: default params
});

// With prefix
const { t } = useTranslation({ keyPrefix: 'profile' });
t('title');  // Translates 'profile.title'

useLocale

Locale management and formatting.

const {
  locale,            // Current locale (e.g., 'en-US')
  language,          // Language code (e.g., 'en')
  isRTL,             // Is right-to-left
  supportedLocales,  // Available locales
  setLocale,         // Change locale
  formatDate,        // Format date
  formatRelativeTime, // Format relative time
  formatNumber,      // Format number
  formatCurrency,    // Format currency
  formatPercent,     // Format percentage
} = useLocale();

useAccessibility

Accessibility features.

const {
  isScreenReaderEnabled,  // Screen reader active
  isReduceMotionEnabled,  // Reduce motion preference
  isBoldTextEnabled,      // Bold text preference
  fontScale,              // Font scale multiplier
  announce,               // Announce to screen reader
  settings,               // Full settings object
} = useAccessibility();

// Announce action completion
announce('Item added to cart', 'polite');

Formatting Examples

Dates

const { formatDate, formatRelativeTime } = useLocale();

// Date styles
formatDate(new Date(), { dateStyle: 'full' });    // "Monday, January 15, 2024"
formatDate(new Date(), { dateStyle: 'short' });   // "1/15/24"
formatDate(new Date(), { timeStyle: 'short' });   // "3:30 PM"

// Relative time
formatRelativeTime(yesterday);  // "yesterday"
formatRelativeTime(lastWeek);   // "7 days ago"

Numbers & Currency

const { formatNumber, formatCurrency, formatPercent } = useLocale();

formatNumber(1234.56);                    // "1,234.56"
formatNumber(1234.56, { style: 'decimal', minimumFractionDigits: 2 });

formatCurrency(99.99, 'USD');             // "$99.99"
formatCurrency(99.99, 'EUR');             // "€99.99"

formatPercent(0.75);                      // "75%"

RTL Support

function RTLAwareComponent() {
  const { isRTL } = useLocale();

  return (
    <View style={{
      flexDirection: isRTL ? 'row-reverse' : 'row',
      textAlign: isRTL ? 'right' : 'left',
    }}>
      <Text>This text respects RTL</Text>
    </View>
  );
}

Pluralization

const { tp } = useTranslation();

// In your resources:
// items: { one: '1 item', other: '{{count}} items' }

tp('items', 0);   // "0 items"
tp('items', 1);   // "1 item"
tp('items', 5);   // "5 items"

Adapter Pattern Benefits

The adapter pattern allows you to:

  1. Swap providers easily - Change from react-i18next to react-intl with one line
  2. Test without real i18n - Use NoOpAdapter or ConsoleAdapter
  3. Debug translations - Use ConsoleAdapter to see all translations
  4. Create custom adapters - Build adapters for any i18n service
// Switch providers without changing any component code:

// Before (react-i18next)
<I18nProvider adapter={new ReactI18nextAdapter({ i18n })}>

// After (custom solution)
<I18nProvider adapter={new MyCustomAdapter()}>

// Your components don't change at all!

TypeScript

Full TypeScript support with exported types:

import type {
  I18nAdapter,
  I18nConfig,
  TranslationParams,
  PluralForms,
  DateFormatOptions,
  NumberFormatOptions,
  AccessibilitySettings,
  LocaleConfig,
} from '@astacinco/rn-i18n';

License

MIT