Make WordPress Core

Opened 3 years ago

Last modified 3 years ago

#52438 new defect (bug)

Theme translations in WP_LANG_DIR are loaded twice, no (logical) way to override from a (child) theme.

Reported by: captaincrash's profile captain.crash Owned by:
Milestone: Future Release Priority: normal
Severity: minor Version: 5.6
Component: I18N Keywords: needs-patch needs-testing
Focuses: Cc:


I was trying to override some translation strings from within a child theme for a (parent) theme that has online translations (from that WordPress downloaded into WP_LANG_DIR/themes/

There are a couple of problems getting this to work, at least one of which (2)) I believe is a bug.

1) Both load_theme_textdomain() and consequently load_child_theme_textdomain() will give priority to .mo files found in WP_LANG_DIR and will completely ignore theme based .mo files when the former exist. I tried to circumvent this with load_textdomain() directly, see here and made it load before the parent theme's call to load_theme_textdomain() in order to make my translations take precedence in the merge. I did like proposed in the docs, i.e. in the child theme's functions file (that loads before the parent's) via the after_setup_theme hook.
The question here is should there be a better (more intuitive) way? Maybe calling load_theme_textdomain() with the parent's text domain again (and make it work, of course)?

2) It did not seem to work, so I tried to log which .mo files WordPress tries loading with this code. This showed that the downloaded translation in WP_LANG_DIR gets called twice. The 2nd call is from the parent theme's load_theme_textdomain() and my effort from 1) successfully put my translaions before that 2nd call. But the 1st .mo file loading... I traced this down to this code within l10n.php: the check with _load_textdomain_just_in_time() actually loads the .mo file via load_textdomain() and way to early. And anyway, does this check make any sense:

if ( isset( $l10n[ $domain ] ) || ( _load_textdomain_just_in_time( $domain ) && isset( $l10n[ $domain ] ) ) )

If isset( $l10n[ $domain ] ) is false, how could the condition after || ever be true?
Removing the OR condition with the call to _load_textdomain_just_in_time() also removes the 1st logged .mo file. Then, my translations from the child theme were the first to load and worked like intended, i.e. merge with the parent's translations that come afterwards.

It also works when calling load_textdomain() in the (child) themes functions file directly (not bound to a hook), but that's not how I understand that this should be done?!

I reproduced the double loading .mo files with a fresh WordPress 5.6 install and the default Twenty Twenty-One theme in formal German language.

I hope, I did not miss anything crucial and this report is of any help.

Change History (5)

#1 @captain.crash
3 years ago

Gently bumping this after three months... Anyone?

#2 @SergeyBiryukov
3 years ago

  • Milestone changed from Awaiting Review to 5.8

#3 @SergeyBiryukov
3 years ago

Hi there, welcome back to WordPress Trac!

Thanks for the report, moving to the 5.8 milestone for investigation.

#4 @desrosj
3 years ago

  • Keywords needs-patch needs-testing added
  • Milestone changed from 5.8 to Future Release

Unfortunately, a contributor has not been able to dive into this one to investigate. The 5.8 deadline is today, so this will need to be punted. I'm punting to Future Release, but once this has more information and a patch, it can be moved back to a numbered milestone.

@ocean90 @swissspidy Do you happen to have any insight here?

#5 @ilovecats7
3 years ago

theme that has online translations (from that WordPress downloaded into WP_LANG_DIR/themes/

I can't seem to reproduce this. I'm using a fresh install of WordPress 5.8, the Twenty Twenty-One theme, and when I switch the language (in Settings > General > Site Language), the theme strings don't change. Is there something else that I need to do in order for WordPress to download the translations from

Note: See TracTickets for help on using tickets.