11

I'm using WordPress in french with the plugin The Events Calendar.

This plugin comes with a bundled french translation but it has some mistakes. I want to fix them but replacing the original file is a bad idea since it's gonna be replaced with the next update. I contacted the developer to submit a fix but it may take some time.

In the meantime, I would like to load a duplicate I did from my template directory. I already tried multiple things like:

load_plugin_textdomain( 'tribe-events-calendar', get_template_directory() . '/languages' );

Or with

add_filter('override_load_textdomain', …)

in my functions.php but it doesn't seem to work. The only thing I was able to do is disabling the load of the original translation file.

Is there any way to replace a plugin translation file on load? I use WPML too but in "Translate with .mo files" mode not in "Translate with WPML" so I can't change plugin translation on the fly. Maybe WPML can load my own translation of The Events Calendar?

LeBen
  • 1,884
  • 12
  • 21

3 Answers3

13

You can add this few lines in your functions.php theme file

$text_domain = 'the-events-calendar';
$original_language_file = ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'the-events-calendar' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'the-events-calendar-fr_FR.mo';
$override_language_file = ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'your-own-theme' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'the-events-calendar-fr_FR.override.mo'; 

// Unload the translation for the text domain of the plugin
unload_textdomain($text_domain);
// Load first the override file
load_textdomain($text_domain, $override_language_file );
// Then load the original translation file
load_textdomain($text_domain, $original_language_file );

You'll have to replace the two file variables with the actual language file.

But we'll suppose that the french language file is in the plugin language folder and your override language file is in the language theme folder.

The idea is to :

  • Un load the language that has already been loaded automatically by WP
  • Load your override file first. This is important to load it first, because already defined translations will be skipped when you'll load another language file for this text domain (see WP core).
  • Load the original translation file, which will in fact load all the untranslated strings of the override file.

This works only with compiled mo file.

You can only add to your override file the few strings you want to override.

Jiwoks
  • 519
  • 5
  • 18
  • This should be the accepted answer. I believe this is the Wordpress way – Alexandre Bourlier Jan 31 '17 at 17:16
  • Excellent. You should just get rid of the "$path ." on the last line – Christer Fernstrom Mar 20 '17 at 13:40
  • @ChristerFernstrom you're right, I've just removed it – Jiwoks Mar 20 '17 at 15:07
  • This will override ALL languages. – vee Apr 11 '17 at 12:23
  • Yes short solution here. It would be better to use the load_textdomain hook to check whether or not the loaded file is the file you want to override – Jiwoks Apr 12 '17 at 10:24
  • I don't recommend this if it can be avoided. When you update the plugin, if there are new strings, you won't get the translations for them, and your site will end up with some parts in English. So unless you're prepared to potentially need to revise your whole translations every time the plugin author feels like changing the strings, I recommend overwriting individual phrases with the "gettext" filter and your own theme's text domain. – Ariane Dec 06 '18 at 21:53
  • As an extra help: [`_get_path_to_translation_from_lang_dir($textdomain)`](https://developer.wordpress.org/reference/functions/_get_path_to_translation_from_lang_dir/) helps you get the current translation file path. – Philip Mar 10 '22 at 16:50
8

I am the author of the Transposh plugin,

Your answer actually is in the following four filters:

   add_filter('gettext', ......, 3);
   add_filter('gettext_with_context', ......, 3);
   add_filter('ngettext', ......, 4);
   add_filter('ngettext_with_context', ....., 4);

(Naturally, you need to add the function and the priority instead of the .....)

Those functions will get the strings and the domain, and you can use those to do functions like:

function gettext_filter($translation, $orig, $domain) {
    if ($domain == 'plugin_domain') {
        if ($orig == 'some text') {
            return "some translation";
        }
    }
    return $translation;
}
marcusds
  • 784
  • 1
  • 7
  • 26
oferwald
  • 91
  • 1
  • Actually I would like to replace the entire translation file, not each string manually. Thanks anyway. – LeBen Oct 08 '13 at 09:08
  • 1
    I was looking for the same for another plugin. This solutions is handy, but it seems quite poor from a performance perspective. Adding a filter to run a function for each and every single call to gettext, with a conditional check to see if a string being handled at the given moment would by any change happen to be the one we're interested in.. this requires the gettext_filter function to run maybe hundreds of times for each page load just to translate one string that will be there only a fractions of the time.. this can't be good if you want to optimize a busy site for performance. – mikkelbreum Dec 05 '13 at 14:07
  • The better way to do this would be to override the entire .mo file in the same manner that many plugin templates allows for override of templates by simply placing alternative versions in the theme root. – mikkelbreum Dec 05 '13 at 14:12
  • It seems the correct way to do is is actually by overriding the entire mo file. I haven't worked much with this yet, and I'm not sure if it requires specific support by the plugin in question, but take a look at this thread for some guidance: http://wordpress.stackexchange.com/questions/30555/how-to-keep-plugin-translates-after-updates – mikkelbreum Dec 05 '13 at 14:16
  • Beware, though, that replacing the entire mo file means you won't get any updates for the plugin translations at all, even if the strings change in the source PHP. If the plugin changes one of its strings, you won't have a translation for it in your own file. – Ariane Apr 22 '20 at 20:08
4

This solution uses wordpress's automatic loaders to override the plugin and doesn't need additional programming logic, instead it lets the CMS do the override.

Let's say you want to translate a plugin called my-plugin. A properly built plugin would have two translated files in the directory wp-content/languages/plugins/ called my-plugin-fr_FR.po and my-plugin-fr_FR.mo. (The locale fr_FR is just my example for French translation, it works respectively for other language translations).

If your plugin has this structure, the steps below will override the translations, if not you can try and see anyway:

  1. Copy the .po and .mo files mentioned above into the directory wp-content/languages/my-plugin. If the directory doesn't exist, create it.
  2. Edit the translation files as you wish and save them.
George Dimitriadis
  • 1,681
  • 1
  • 18
  • 27