I need to add a language file to an existing plugin. Not for translation reasons, but because I'd like to change all occurrences of a certain word to something else. While I could just drop another .po/.mo file set into the plugin's languages directory, I don't want to lose the language file when the plugin is updated.

It appears if the plugin used load_textdomain to pull files from the WP_LANG_DIR in addition to load_plugin_textdomain then I could just drop in some .po files into /wp-content/languages/ and it would work.

BuddyPress does it this way, and has instructions for doing the exact sort of thing I'm trying to do: http://codex.buddypress.org/getting-started/customizing/customizing-labels-messages-and-urls/. I've changed every reference to "Group" to "Community".

All I have to do is drop the correctly-named files into the /wp-content/languages/ directory and the files are loaded.

The plugin I'm trying to modify is: BuddyPress Group Email Subscription.

It loads the languages using this function:

function activitysub_textdomain() {
    load_plugin_textdomain( 'bp-ass', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
add_action( 'init', 'activitysub_textdomain' );

3 Answers 3


Best way to do this is probably by using a second, custom-made, plugin.

Make a new plugin directory. Call it something like "example-com-custom-langs" or something unique to your site. In there, make a php file with a plugin header describing what the plugin does (for your own sanity), and do something like this:


function example_com_custom_langs_plugins_loaded() {
  remove_action('init', 'activitysub_textdomain'); // disable the old lang files
  add_action('init','example_com_custom_langs_init'); // load our new lang files

function example_com_custom_langs_init() {
  load_plugin_textdomain( 'bp-ass', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );

Now, you can put your language files into the /languages directory of this new plugin, and they will be loaded instead of the originals in the other plugin. And this plugin won't get updated when the other plugin updates. So as long as they don't change from "bp-ass" as the textdomain, yours get used instead.

  • I like this approach but since I'm already dropping files into wp-content/languages I want to keep in consistent and have all the .po files in there.
    – jjeaton
    Nov 14, 2013 at 0:05
  • The /wp-content/languages folder is now a core managed folder in 3.7, due to language packs. It's not safe to put custom-made language files in there, because the auto-upgrade process can and will overwrite them with official versions. This is not being done yet, but the support is there in 3.7 and it will do exactly that when we implement it on WordPress.org, on a wider-scale.
    – Otto
    Nov 14, 2013 at 0:54
  • Ah, great point, thanks for that. I'll have to adjust how I do it for BuddyPress as well.
    – jjeaton
    Nov 14, 2013 at 14:31
  • What about still using the load_textdomain_mofile filter within a separate plugin?
    – jjeaton
    Nov 14, 2013 at 14:33
  • 1
    Using that filter will work as well.
    – Otto
    Nov 14, 2013 at 17:03

I belive you can use a load_textdomain_mofile filter...

add_filter('load_textdomain_mofile', 'custom_load_textdomain_mofile', 10, 2);
function custom_load_textdomain_mofile( $mofile, $domain){
    if ($domain == 'bp-ass')
        $mofile = 'somepath/to/your/mo/file.mo';
    return $mofile;

Difference (comparing Otto) is you can actually specify your mo file for domain doesn't metter how will be changed (triggered) localization.

  • This worked great and was easy to add.
    – jjeaton
    Nov 14, 2013 at 0:05

The buddypress way is idiotic, you should not use translation to impact server and software behavior, translation should be only for labels (just spent an hour yesterday trying to figure why a CPT wasn't working and it turned out because its type was translatable and I translated it).

Otto's and Oleg's answers are technically correct, but there is one issue they ignore - future upgrades. An upgrade of the plugin will eventually discard the strings you want to override and then your changes will disappear, and since this change is not part of the actual code no one will remember what you have done and will be able to do it again. In addition, depending on the type and amount of changes that you intent to make, you might make any documentation the plugin has unuseable.

In other words, you are forking the plugin's code and an upgrade will kill your changes in any case, so why not to do them at code level where they will be easy to find, and then change the plugin name and slug to prevent it from being upgraded by mistake.

clarification: assume the original plugin has an <? _e('give me money!','text-domain')?> and you want that instead of printing "give me money!" you want that "give me your money please" will be printed and you use the methods described in the other answers to achieve that.

Some version later the author of the plugin decides to emphasize the sentence and replaces it with <? _e('GIVE ME THE MONEY!','text-domain')?>, but the new string is not in the modified translation table that was used as part of the solution and therefor instead of getting the expected "give me your money please" you get "GIVE ME THE MONEY!". This is a bug that will be hard to figure out because by the time it will happen you will forget what kind of a hack you have done originally.

  • Upgrades to the first plugin will not change the second plugin.
    – fuxia
    Nov 6, 2013 at 19:24
  • I don't get it... both solutions are upgrade-proof... Maybe you want to emphasize that new translations won't carry over when the main plugin is updated?
    – brasofilo
    Nov 6, 2013 at 20:18
  • It's fairly trivial to merge the new translations into an existing .po file using PoEdit.
    – jjeaton
    Nov 6, 2013 at 21:03
  • it will not change the second but it will change the result Nov 6, 2013 at 21:21
  • @jeaton, true, but then you need to merge only when you have forked and you need also to remember that you have forked and you need to merge. The nice thing about "automatic" plugin upgrades is that they assume you haven't forked. Nov 6, 2013 at 21:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.