End the Use of 'gettext' Filter - Better Alternative? #49

deckerweb opened this Issue Nov 25, 2013 · 9 comments

4 participants


The general principle Justin implemented in Hybrid Core for having only one translation file in the end is really awesome! Congrats on that :)

However, the whole system currently works with the 'gettext' filter from WordPress core. That filter can cause big performance issues - these might not happen on smaller installs - but in general the 'gettext' filter is dangerous by design.

It always scans all existing translation files/ textdomains for any string - and that on every page load. For 20 strings that may be ok, but not for 200 or 2000 strings. It slows down the whole site and can lead to crashing whole sites or servers...

I speak from experience, I won't panic here, just give this thought for consideration. The 'gettext' filter should - in my opinion - be removed from WordPress core as it is too tempting for devs to use it, even knowing its down sides. Again, I speak from experience here. Also, I discussed that with a few other devs, that have way more expertise than me and they all agree with that: NOT using this filter at any time!

Currently, the only working alternative is, to use the $l10n global variable which has stored all the translation strings. That is also not elegant but should avoid performance issues.

The general implementation of that $l10n global can be seen here: http://byotos.com/2010/04/08/hijacking-wordpress-internationalisation/ and here http://bp-tricks.com/coding/string-replacement-hack-core/ also in older 2.x versions of the "Welcome Pack" plugin for BuddyPress. Also, the newest version 1.4.0+ of my "bbPress String Swap" plugin is using that technique.

In general, a better solution for things like Hybrid Core is doing - or plugins like above - is needed in WordPress core. The whole POMO management needs lots of performance improvements! Also, the implementation of "language packs" for themes and plugins needs to be refined and to allow more flexibility and exceptions, as to say, for Hybrid Core for example.

I am leaving this here for further discussion.

Thanks, Dave from Germany :)


Also Pippin have short article about it. http://pippinsplugins.com/dangers-gettext-filter/

Hybrid Core Themes usually have 200-300 strings. Is there someway to test does that have real impact on speed?


The whole localization subsystem is performance bottleneck, at really high speed - even without anything hooked into it.

So question is (in context of Hybrid Core) - which scenarios there is concern about and how much are they slowing things down (as in getting profiler out and measuring)?


@samikeijonen Yes, know that post, everyone should be aware of it... :)
The 200-300 strings may be ok, but gettext goes through all of them for any textdomain! It also depends on server config etc.

Also, if any other instance of gettext filter is used then together with Hybrid Core system it gets even worse. So, you never know which plugins users have installed that may actually use that filter too. Then "apply_filters" runs through even more instances!!!

Imagine an install: localized WP, fully localized Hybrid Core parent theme, localized child theme (let's say for WooCommerce with extra strings) plus WooCommerce shop and some Woo extensions plus other plugins. Such an install would go down really "fast"...!

@Rarst Fully agree on the bottleneck.
The other thing regarding scenarious: as I mentioned in the above example, you never know where Hybrid theme is used so it should be optimized from start as much as possible.

Again, it's no criticism or anything, just discussion if there's anything better or whatever - even if not for Hybrid, I am also always on the search to learn new stuff about i18n... :)


Regarding scenarious: I have a language pack plugin which used to swap 2 (TWO!) strings within the 'woocommerce' textdomain - currently around 2,500 strings or so - this led to strong performance issues on various user installs. Also, I could feel it directly on my own installs, and simple measuring by "P3" profiler plugin brought up, that these gettext filter needed more memory/performance than WooCommerce base plugin itself (which also could be a "monster" sometimes...).


I already knew this might be a cause for performance concern when I first added it. I just didn't know of anything else to do about it at the time. I needed a solution, and this one worked. This has been on my list of things to change for a while.

I really dislike messing around with globals, but $l10n looks promising.

For anyone not up to speed on the issue we need a better fix for:

Hybrid Core has its own textdomain of hybrid-core. Themes built on Hybrid Core have their own textdomain of theme-slug. However, the translations of Hybrid Core text strings will most likely be within the translations of the theme. So, we need to swap the hybrid-core textdomain with the theme-slug textdomain. Currently, this swap is handled on the gettext filter hook.


I've tried to come at this in several different directions over the past months. I had abandoned all hope, but I think I may have gotten this thing licked in this commit: 40c2dba

Putting me onto the $l10n global was part of the reason I managed this.

This ticket has some changes that may mess with some devs in some edge cases:

  • Textdomains are loaded later than they were before (now with a 25 priority on after_setup_theme). This is because of the extensions we need to check. I doubt this is an issue for most, but it could be if someone is building anything off of loading textdomains related to the framework.
  • The framework will no longer load its own, separate MO file. No one was doing this anyway as far as I know. Theme authors have been pulling the text strings into their theme translation files. WP's translation tools is going to do this automatically, which I assume most folks are using.

I don't think those things are going to mess up anybody. I just wanted to throw the warning up there in case it did.

What I need is simply for a few folks to test translations with the new method. Make sure it's working. And, of course, look over the code and let me know if I'm creating a bigger problem. This is the best way I could think of handling our textdomain situation.


I'll test in a sec.


I didn't noticed any issues with this.


Based on my own tests and feedback from @samikeijonen, I'm closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment