Is it enough to just create a child-theme – let’s say technically without adding anything else but the bare minimum style.css
– to have the translation of the parent-theme being used automatically for the child-theme as well?
child-theme/style.css
/**
* Theme Name: Child-Theme Child
* Theme URI: http://example.com/
* Description: Child theme for the Twentytwelve theme
* Author: Theme Author
* Author URI: http://example.com/
* Template: twentytwelve
* Version: 0.1.0
*/
The twentytwelve theme has the standard language translation files.
And if that does not happen automatically on my site, what would be a good place to start trouble-shooting the missing translation?
Basically, the answer is NO, … but… there’s an option:
Add a mu-plugin.
This (MU-)Plugin does several things:
after_setup_theme
on a priority of 20 – assuming that the parent textdomain/i18n .mo file is loaded correctly at the default priority on the correct hook.instanceof
theWP_Theme
– in this case the child theme.It’s actually quite easy, as the core class does a lot of checks for us: It retrieves another instance of
WP_Theme
for the parent theme. Then it checks if theTextDomain
header is set, using:$current_theme->get( 'TextDomain' );
. The point therefore is there comes one convention into the game: This plugin will only work, if the parent theme got aText Domain
and(!) aDomain Path
header set.Now here comes the problem: The default/standard Twenty* themes delivered by core do not(!) have the
Domain Path
header entry. And this is something that we have to fix instantly, asload_theme_textdomain()
else searches for the translation file not in the Parent theme folder, butget_stylesheet_directory().WP_Theme::get( 'DomainPath' )
, which means that (A) theDomain Path
needs to be set and it needs to be prefixed with a slash:/
.WP_LANGUAGE_DIR.'/themes'
directory.Note: I guess that’s just a bug that will never be fixed for “backwards compatibility”, which – in other words – means that there is a bug, but there may be devs already working around it. 😛
Then there’s another problem. The
WP_Theme
class methodload_textdomain()
internally passes a$path
toload_theme_textdomain()
. And this parameter is$this->get_stylesheet_directory()
. And this method returns$this->theme_root . '/' . $this->stylesheet
. So the function would actually work quite good, but it’s messing it up with simply calling an internal replacement forget_stylesheet_directory()
(which would have been filterable). One might now thinkWrong. All the class properties are marked
private
and inaccessible.Then you might think
Wrong. The class itself is
final
and not extensible.Result: We’re left with what
load_theme_textdomain()
– the last function in the chain of calls – offers us. Now we got a larger plugin that intercepts theload_theme_textdomain()
call to load the correct file. To not disturb other i18n file loads, it instantly removes the callback from the filter to keep your environment tidy.By default this just works out of the box. If the parent theme offers translation, the child-theme takes it over.
If it does not work something is wrong. This was in my case, here is how I did trouble-shoot that:
?XDEBUG_SESSION_START=1
) and verified the loading position that was reported broken by placing a breakpoint there and stepping into it.It then turned out that WordPress was looking for a different file-name. I corrected the filename and it then worked.
Morale of the story: Language files inside themes should be named with the local only, like
de_DE.mo
in my case.Faulty:
Working: