solvebeam/wp-text-domain-replacer

There is no license information available for the latest version (v1.0.0) of this package.

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

Maintainers

Package info

github.com/solvebeam/wp-text-domain-replacer

pkg:composer/solvebeam/wp-text-domain-replacer

Statistics

Installs: 770

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 1

v1.0.0 2026-03-23 19:33 UTC

This package is auto-updated.

Last update: 2026-05-13 12:13:35 UTC


README

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

Latest Stable Version Total Downloads License

Table of contents

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, 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

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

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

Options

--dir=DIRECTORY

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

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

The text domain to replace with. This is required.

Example: --replace=new_domain

--exclude=PATTERN

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

Example: --exclude=node_modules --exclude=vendor

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

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.

Configuration via composer.json

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

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

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

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

Here is a list of alternatives that we found:

npm

Links