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

rn-localize

v1.0.2

Published

Auto-extract hardcoded strings from React Native projects for localization. A zero-config CLI that parses your AST, generates translation keys, and rewrites your source code.

Readme

rn-localize

Auto-extract hardcoded strings from React Native projects for localization.

rn-localize scans your React Native codebase, extracts all hardcoded strings from JSX/TSX/JS/TS files using AST parsing, generates human-readable translation keys, and writes an en.json localization file. It can also optionally rewrite your source files to replace hardcoded strings with t('key') calls.

Installation

# Run directly with npx (no install needed)
npx rn-localize scan

# Or install globally
npm install -g rn-localize

# Or install locally in your project
npm install --save-dev rn-localize

Usage

Basic Scan

# Scan ./src and write to ./i18n/en.json
npx rn-localize scan

# Scan a custom directory
npx rn-localize scan --src ./app

# Dry run — preview without writing files
npx rn-localize scan --src ./app --dry-run

Rewrite Mode

Automatically replace hardcoded strings with t() calls:

# Full rewrite mode
npx rn-localize scan --src ./src --rewrite --output ./locales/en.json

⚠️ IMPORTANT: You must create an i18n.ts file! When using --rewrite, the CLI automatically calculates the relative path from every modified file to the root of your --src folder and injects an import statement for an i18n module (e.g. import { t } from '../../i18n';).

You MUST create an i18n.ts or i18n.js file at the root of your scanned directory (./src/i18n.ts) that exports a t function:

// src/i18n.ts
import en from '../locales/en.json';

export function t(key: string): string {
  const parts = key.split('.');
  let current: any = en;
  for (const part of parts) {
    if (current && typeof current === 'object' && part in current) {
      current = current[part];
    } else {
      return key;
    }
  }
  return typeof current === 'string' ? current : key;
}
# Custom i18n import
# Note: If you provide a custom --import, dynamic relative path injection is bypassed.
npx rn-localize scan --rewrite --import "import { t } from '@/utils/i18n';"

### All Options

| Option | Default | Description |
|---|---|---|
| `-s, --src <path>` | `./src` | Source directory to scan |
| `-o, --output <path>` | `./i18n/en.json` | Output file path |
| `-l, --lang <code>` | `en` | Language code for output file |
| `--rewrite` | `false` | Rewrite source files with `t()` calls |
| `--import <statement>` | `import { t } from '../i18n'` | Import line to inject when rewriting |
| `--ignore <patterns>` | `node_modules,**/*.test.*,**/*.spec.*` | Comma-separated glob patterns to ignore |
| `--dry-run` | `false` | Preview output without writing any files |
| `--no-map` | `false` | Omit source location map file |
| `--prefix <name>` | (auto from filename) | Manually set key prefix for all keys |
| `--min-length <n>` | `2` | Minimum string length to extract |
| `--overwrite` | `false` | Overwrite existing keys instead of merging |

## Output Format

### Translation File (`en.json`)

```json
{
  "home_screen": {
    "already_have_an_account": "Already have an account?",
    "get_started": "Get Started",
    "good_morning_hope_you_have_a_great_day": "Good morning! Hope you have a great day.",
    "search_here": "Search here...",
    "welcome_back": "Welcome back"
  },
  "profile_screen": {
    "edit_profile": "Edit Profile",
    "submit": "Submit"
  }
}

Source Map File (en.json.map)

A parallel file with source locations for each key:

{
  "home_screen.welcome_back": {
    "file": "src/screens/HomeScreen.tsx",
    "line": 42
  }
}

What Gets Extracted

| AST Node | Example | Extracted? | |---|---|---| | JSX text | <Text>Welcome</Text> | ✅ | | String props | <Input placeholder="Search" /> | ✅ | | Static template literals | const msg = `Hello` | ✅ | | Props: testID, key, style, etc. | <View testID="btn" /> | ❌ Skipped | | URLs | https://example.com | ❌ Skipped | | Hex colors | #FF0000 | ❌ Skipped | | Already wrapped in t() | t('key') | ❌ Skipped | | Inside StyleSheet.create() | Style values | ❌ Skipped | | Template literals with expressions | `Hello ${name}` | ❌ Skipped |

Key Generation

Keys are generated from the filename and string content:

{screen_name}.{string_slug}

HomeScreen.tsx + "Welcome back" → home_screen.welcome_back
ProfileScreen.tsx + "Submit"    → profile_screen.submit

Collision handling: if two different strings produce the same key, suffixes _2, _3 are appended.

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Run locally
npm run dev -- scan --src ./tests/fixtures --dry-run

License

MIT