Wordpress - Override parent theme translation on child theme

I think I found a solution, but before a little

Premise

load_theme_textdomain() and load_child_theme_textdomain() are basically equal, the only difference is the default path they use:

  • they get the current language (using get_locale()) and add the relative .mo file to the path passed as argument;
  • then they call load_textdomain() passing as argument both the textdomain and the resulting path to the .mo file.

Then load_textdomain loads the .mo file into the global textdomain variable, but as we can read from the source:

If the domain already exists, the translations will be merged.

If both sets have the same string, the translation from the original value will be taken.

So, in order to override/replace just the strings of the theme parent we want, we need to load a custom .mo file for the parent textdomain, containing just those strings translated, before the parent theme load its .mo file.


Solution

In the end, I simply created a folder with the name of the parent theme (just for convenience) into the child theme languages folder, and put inside it my custom .mo files for the parent textdomain (one for language, in the xx_XX.mo form, where xx_XX is the language code).

And then I added a line in my child theme functions.php file during the after_setup_theme action, near the one that loads the .mo file for my child theme textdomain:

add_action( 'after_setup_theme', function () {
    // load custom translation file for the parent theme
    load_theme_textdomain( 'parent-textdomain', get_stylesheet_directory() . '/languages/parent-theme' );
    // load translation file for the child theme
    load_child_theme_textdomain( 'my-child-theme', get_stylesheet_directory() . '/languages' );
} );

Because the functions.php file of the child theme is loaded before the parent's one, this set of strings will have precedence over the parent theme translation (or I could've just set the priority using the third parameter of the add_action function).


Note: I could have use load_child_theme_textdomain instead of load_theme_textdomain, as said in the premise it would've been the same.


You can use language files that are in your child theme folder. First you have to know which text domain the parent theme is using. Then create the .po and .mo files with only your language as the file name (e.g. de_DE.po/de_DE.mo or nl_NL.po/nl_NL.mo) and put them into a folder within your child theme directory, "languages" for example.

You can then initialize the text domain with load_child_theme_textdomain():

load_child_theme_textdomain( 'the_text_domain', get_stylesheet_directory() . '/languages/' );

Note that you can find the text domain by looking for function calls like __() or _e() within the parent theme PHP files. The second parameter is the text domain: __( 'Translated text string', 'text_domain' );


A 2019 update for Wordpress 5.0.1.

  1. The files shall NOT have the parent or child slug in them. For example, providing spanish Mexican translation should have files child-theme-name/languages/es_MX.po and /child-theme-name/languages/es_MX.mo
  2. The child theme functions.php should have the following code. Notice that the function load_child_theme_textdomain() first parameter is the PARENT theme slug, not the child's:
function child_theme_slug_setup() {
    load_child_theme_textdomain( 'parent-theme-slug', get_stylesheet_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'child_theme_slug_setup' );