PHPackages                             solvebeam/wp-text-domain-replacer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. solvebeam/wp-text-domain-replacer

ActiveLibrary[CLI &amp; Console](/categories/cli)

solvebeam/wp-text-domain-replacer
=================================

A developer tool for replacing WordPress translation text domains in PHP, JavaScript, and `block.json` files.

v1.0.0(3mo ago)1770[1 issues](https://github.com/solvebeam/wp-text-domain-replacer/issues)1PHP

Since Mar 23Pushed 1mo agoCompare

[ Source](https://github.com/solvebeam/wp-text-domain-replacer)[ Packagist](https://packagist.org/packages/solvebeam/wp-text-domain-replacer)[ RSS](/packages/solvebeam-wp-text-domain-replacer/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (1)

SolveBeam WordPress Text Domain Replacer
========================================

[](#solvebeam-wordpress-text-domain-replacer)

A developer tool for replacing WordPress translation text domains in PHP, JavaScript, and `block.json` files.

[![Latest Stable Version](https://camo.githubusercontent.com/58c3925644f34f4158560b79d203fdd6e65316d0cf80d13e27c6b93f289eaa6c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736f6c76656265616d2f77702d746578742d646f6d61696e2d7265706c616365723f7374796c653d666c61742d737175617265)](https://packagist.org/packages/solvebeam/wp-text-domain-replacer)[![Total Downloads](https://camo.githubusercontent.com/1dad0d878209922a8fbdf98c927d813dda8eae9d696d13177c95b11e84ac34da/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736f6c76656265616d2f77702d746578742d646f6d61696e2d7265706c616365723f7374796c653d666c61742d737175617265)](https://packagist.org/packages/solvebeam/wp-text-domain-replacer)[![License](https://camo.githubusercontent.com/7a9ac9691e99a2284ecc110b681e4516f95d8e119ea3723891d4cc826b635ab2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f736f6c76656265616d2f77702d746578742d646f6d61696e2d7265706c616365723f7374796c653d666c61742d737175617265)](https://packagist.org/packages/solvebeam/wp-text-domain-replacer)

Table of contents
-----------------

[](#table-of-contents)

- [Why This Tool Exists](#why-this-tool-exists)
- [Getting Started](#getting-started)
    - [Installation](#installation)
    - [First Run](#first-run)
- [Command Line Usage](#command-line-usage)
    - [Options](#options)
    - [Examples](#examples)
- [Configuration via composer.json](#configuration-via-composerjson)
- [Alternatives](#alternatives)
- [Links](#links)

Why This Tool Exists
--------------------

[](#why-this-tool-exists)

This tool was created for a common WordPress development workflow: reusing existing plugins or libraries inside another plugin or theme.

A well-known example is [Action Scheduler](https://actionscheduler.org/), which explicitly states:

> "Action Scheduler is designed to be used and released in plugins."

That is exactly where translation issues can appear.

When you embed a reusable library, it often keeps its own text domain (for example `action-scheduler`). If your plugin uses another text domain (for example `my-plugin`), WordPress will not automatically treat those strings as part of your plugin's translations.

In practice, this means your plugin can be translated, but embedded library strings may remain untranslated for users.

This package solves that build-time problem by replacing the embedded library text domain with your plugin's text domain across your source files. For example:

```
vendor/bin/wptdr --dir=src --search=action-scheduler --replace=my-plugin
```

After this replacement, all translatable strings consistently use your plugin's domain, so they can be handled in one translation flow. This is especially useful for teams distributing plugins/themes that bundle reusable WordPress components.

Getting Started
---------------

[](#getting-started)

### Installation

[](#installation)

To start replacing text domains in your WordPress plugin or theme, require SolveBeam WordPress Text Domain Replacer in Composer:

```
composer require solvebeam/wp-text-domain-replacer --dev
```

### First Run

[](#first-run)

To replace text domains in your project, use the `wptdr` command from the `vendor/bin/` directory:

```
vendor/bin/wptdr \
  --dir=src \
  --search=old_domain \
  --replace=new_domain
```

This will scan your `src` directory for any occurrence of the text domain `old_domain` in PHP files, JavaScript files, and `block.json` files, and replace them with `new_domain`.

Command Line Usage
------------------

[](#command-line-usage)

### Options

[](#options)

#### `--dir=DIRECTORY`

[](#--dirdirectory)

Specifies the directory to scan for text domain replacements. Defaults to the current working directory if not provided.

**Example:** `--dir=src` or `--dir=.`

#### `--search=DOMAIN`

[](#--searchdomain)

The text domain to search for. You can specify multiple search domains by repeating this option.

**Example:** `--search=old_domain` or `--search=old_domain --search=legacy_domain`

#### `--replace=DOMAIN`

[](#--replacedomain)

The text domain to replace with. This is required.

**Example:** `--replace=new_domain`

#### `--exclude=PATTERN`

[](#--excludepattern)

Exclude directories or files by name. You can specify multiple patterns by repeating this option.

**Example:** `--exclude=node_modules --exclude=vendor`

### Examples

[](#examples)

**Basic replacement in current directory:**

```
vendor/bin/wptdr --search=old_domain --replace=new_domain
```

**Replace in specific directory:**

```
vendor/bin/wptdr --dir=src --search=old_domain --replace=new_domain
```

**Replace multiple text domains:**

```
vendor/bin/wptdr \
  --dir=src \
  --search=old_domain \
  --search=legacy_domain \
  --replace=new_domain
```

**Replace while excluding directories:**

```
vendor/bin/wptdr \
  --dir=. \
  --search=old_domain \
  --replace=new_domain \
  --exclude=vendor \
  --exclude=node_modules
```

**Add to Composer scripts:**

```
{
  "scripts": {
    "update-text-domain": "wptdr --dir=src --search=old_domain --replace=new_domain"
  }
}
```

Then run with:

```
composer update-text-domain
```

Limitations
-----------

[](#limitations)

### PHP-Parser Namespace Resolution

[](#php-parser-namespace-resolution)

The text domain replacer uses PHP-Parser to analyze PHP code. However, PHP-Parser has a fundamental limitation when dealing with function calls inside namespaces:

**Unqualified function names inside a namespace cannot be statically resolved.**

For example, inside the `Test` namespace, a call to `__()` could refer to either:

- The namespaced function `\Test\__()`
- The global WordPress function `\__()`

Because PHP-Parser lacks the runtime context to determine which one is intended, it **cannot statically resolve the fully qualified name (FQN)**.

**Impact on this tool:**

The text domain replacer conservatively assumes that unqualified translation function calls might be WordPress functions and modifies them accordingly. This means:

- A custom namespaced `__()` function in your code **will have its calls modified** by the replacer, even though it's not the WordPress translation function
- To prevent this, use fully qualified names: `\YourNamespace\__()` for custom functions or `\__()` for WordPress functions

**Example:**

```
namespace MyPlugin;

function __( $text, $domain ) {
    // Custom implementation
    return "$text [$domain]";
}

// This WILL be modified by the replacer (treated as potential WordPress __() call):
__( 'Test', 'old_domain' );  // Becomes: __( 'Test', 'new_domain' );

// This will NOT be modified (explicitly namespaced):
\MyPlugin\__( 'Test', 'old_domain' );  // Remains unchanged
```

For more details, see the [PHP-Parser Name Resolution documentation](https://github.com/nikic/PHP-Parser/blob/master/doc/component/Name_resolution.markdown).

Configuration via composer.json
-------------------------------

[](#configuration-via-composerjson)

Instead of passing all options via command line, you can also configure the text domain replacer in your `composer.json` file. This is useful for keeping your configuration in one place and simplifying your Composer scripts.

### Setup

[](#setup)

Add a new `extra` section to your `composer.json`:

```
{
  "extra": {
    "solvebeam-wp-text-domain-replacer": {
      "dir": "src",
      "search": [
        "old_domain",
        "legacy_domain"
      ],
      "replace": "new_domain",
      "exclude": [
        "vendor",
        "node_modules"
      ]
    }
  }
}
```

### Running with Configuration

[](#running-with-configuration)

Once configured in `composer.json`, you can run the tool without any options:

```
vendor/bin/wptdr
```

The tool will automatically load the configuration from `composer.json` and apply it.

### Overriding Configuration

[](#overriding-configuration)

Command-line options always take precedence over `composer.json` configuration. This allows you to override specific settings when needed:

```
# Use composer.json config but override the directory
vendor/bin/wptdr --dir=tests

# Use composer.json config but override the replacement domain
vendor/bin/wptdr --replace=another_domain

# Use composer.json config but replace different domains
vendor/bin/wptdr --search=other_domain
```

Alternatives
------------

[](#alternatives)

Here is a list of alternatives that we found:

- [Automattic Babel Plugin Replace TextDomain](https://www.npmjs.com/package/@automattic/babel-plugin-replace-textdomain)
- [wp-textdomain](https://www.npmjs.com/package/wp-textdomain)
- [wp-cli-textdomain](https://github.com/varunsridharan/wp-cli-textdomain)
- [WordPress Coding Standards I18n Text Domain Fixer](https://github.com/WordPress/WordPress-Coding-Standards/blob/trunk/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php)
- [WooCommerce TextDomain Script](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/bin/package-update-textdomain.js)

npm
---

[](#npm)

-
-

Links
-----

[](#links)

-
-
-
-
-
-
- [https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#wordpressutilsi18ntextdomainfixer-replace-a-text\_domain](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#wordpressutilsi18ntextdomainfixer-replace-a-text_domain)

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance67

Regular maintenance activity

Popularity21

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

92d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/869674?v=4)[Remco Tolsma](/maintainers/remcotolsma)[@remcotolsma](https://github.com/remcotolsma)

---

Top Contributors

[![remcotolsma](https://avatars.githubusercontent.com/u/869674?v=4)](https://github.com/remcotolsma "remcotolsma (14 commits)")

---

Tags

block-editorcliglotpressgutenberg-blocksi18njavascriptphpphpcbfpoeditsolvebeamtranslationwordpresswordpress-developmentwpwp-cliwpcli

### Embed Badge

![Health badge](/badges/solvebeam-wp-text-domain-replacer/health.svg)

```
[![Health](https://phpackages.com/badges/solvebeam-wp-text-domain-replacer/health.svg)](https://phpackages.com/packages/solvebeam-wp-text-domain-replacer)
```

###  Alternatives

[seld/cli-prompt

Allows you to prompt for user input on the command line, and optionally hide the characters they type

24726.4M22](/packages/seld-cli-prompt)[illuminate/console

The Illuminate Console package.

13045.3M6.2k](/packages/illuminate-console)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
