Laden untergeordnete Themen die Übersetzung automatisch aus dem übergeordneten Thema?

7

Reicht es aus, nur ein untergeordnetes Thema zu erstellen - sagen wir technisch, ohne etwas anderes als das Nötigste hinzuzufügen style.css-, damit die Übersetzung des übergeordneten Themas auch automatisch für das untergeordnete Thema verwendet wird?

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
 */

Das zwanzigundzwanzigste Thema enthält die Standard-Sprachübersetzungsdateien.

Und wenn dies auf meiner Website nicht automatisch geschieht, was wäre ein guter Ort, um die fehlende Übersetzung zu beheben?

hakre
quelle

Antworten:

7

Reicht es aus, nur ein untergeordnetes Thema zu erstellen - sagen wir technisch, ohne etwas anderes als das absolute Minimum an style.css hinzuzufügen -, damit die Übersetzung des übergeordneten Themas auch automatisch für das untergeordnete Thema verwendet wird?

Grundsätzlich lautet die Antwort NEIN , ... aber ... es gibt eine Option:

Fügen Sie ein Mu-Plugin hinzu.

Dieses (MU-) Plugin macht verschiedene Dinge:

  1. Es wird after_setup_themeeine Priorität von 20 festgelegt - vorausgesetzt, die übergeordnete Textdomain / i18n .mo-Datei wird korrekt mit der Standardpriorität für den richtigen Hook geladen .
  2. Dann ruft es instanceofdas WP_Theme- in diesem Fall das untergeordnete Thema - ab.
  3. Dann überprüft er , ob es tatsächlich ist ein Kind Thema in Gebrauch.
  4. Wenn dies zutrifft, wird nur die Textdomäne aus der übergeordneten Datei geladen.

Es ist eigentlich ganz einfach, da die Kernklasse viele Überprüfungen für uns durchführt: Sie ruft eine weitere Instanz WP_Themefür das übergeordnete Thema ab. Anschließend wird überprüft, ob der TextDomainHeader gesetzt ist, indem : $current_theme->get( 'TextDomain' );. Der Punkt ist also, dass es eine Konvention im Spiel gibt: Dieses Plugin funktioniert nur , wenn das übergeordnete Thema einen Text Domainund (!) Einen Domain PathHeader-Satz hat.

<?php
/**
 * Plugin Name: (#113391) Parent Theme i18n Autoloader
 * Description: Load Twenty12 Child theme translation files automagically from Parent
 */
add_action( 'after_setup_theme', 'wpse113391_parent_theme_i18n_autoloader', 20 );
function wpse113391_parent_theme_i18n_autoloader()
{
    $current_theme = wp_get_theme();
    if ( is_child_theme() )
        $current_theme->parent()->load_textdomain();
}

Hier kommt nun das Problem: Die von Core gelieferten Standard- / Standard-Twenty * -Themen haben (()) keinen Domain PathHeader-Eintrag. Und das müssen wir sofort beheben , da load_theme_textdomain()sonst die Übersetzungsdatei nicht im übergeordneten Themenordner, sondern gesucht wird

  • zuerst im untergeordneten Themenordner : get_stylesheet_directory().WP_Theme::get( 'DomainPath' ), was bedeutet, dass (A) das Domain Pathgesetzt werden muss und ein Schrägstrich vorangestellt werden muss : /.
  • dann im untergeordneten Themenordner: `get_stylesheet_directory (). '/ Languages'.
  • und zuletzt im WP_LANGUAGE_DIR.'/themes'Verzeichnis in.

Hinweis: Ich denke, das ist nur ein Fehler, der aus Gründen der "Abwärtskompatibilität" niemals behoben wird. Mit anderen Worten, es liegt ein Fehler vor, aber möglicherweise arbeiten bereits Entwickler daran. : P.

Dann gibt es noch ein anderes Problem. Die WP_ThemeKlassenmethode load_textdomain()übergibt intern ein $pathan load_theme_textdomain(). Und dieser Parameter ist $this->get_stylesheet_directory(). Und diese Methode kehrt zurück $this->theme_root . '/' . $this->stylesheet. Die Funktion würde also eigentlich ganz gut funktionieren , aber sie bringt es durcheinander, einfach einen internen Ersatz für aufzurufen get_stylesheet_directory()(was filterbar gewesen wäre). Man könnte jetzt denken

"Hey! Die Klasse implements ArrayAccess! Also setze einfach den fehlenden Array-Schlüssel von Domain Path!"

Falsch. Alle Klasseneigenschaften sind markiert privateund nicht zugänglich.

Dann könnten Sie denken

"Warum nicht einfach extenddie WP_ThemeKlasse und eine set()Methode definieren, damit wir die fehlenden Header-Einträge manuell festlegen können?"

Falsch. Die Klasse selbst ist finalund nicht erweiterbar.

Ergebnis: Wir bleiben mit dem, was load_theme_textdomain()uns - die letzte Funktion in der Anrufkette - bietet. Jetzt haben wir ein größeres Plugin, das den load_theme_textdomain()Aufruf abfängt , um die richtige Datei zu laden . Um das Laden anderer i18n-Dateien nicht zu stören, wird der Rückruf sofort aus dem Filter entfernt, um die Umgebung sauber zu halten.

<?php
/**
 * Plugin Name: (#113391) Parent Theme i18n Autoloader
 * Description: Load Twenty12 Child theme translation files automagically from Parent
 */

add_action( 'muplugins_loaded', array( 'WPSE113391Parenti18nLoader', 'getInstance' ) );
class WPSE113391Parenti18nLoader
{
    public static $instance = null;

    private $theme = null;

    public static function getInstance()
    {
        null === self::$instance AND self::$instance = new self;
        return self::$instance;
    }

    public function __construct()
    {
        add_action( 'after_setup_theme', array( $this, 'i18nAutoloader' ), 20 );
    }

    public function setTheme( $theme )
    {
        return $this->theme = $theme;
    }

    public function getTheme()
    {
        return $this->theme;
    }

    public function i18nAutoloader()
    {
        if ( ! is_child_theme() )
            return;

        $current_theme = wp_get_theme();
        if ( '' === $current_theme->parent()->get( 'DomainPath' ) )
        {
            $this->setTheme( $current_theme->parent() );
            add_filter( 'override_load_textdomain', array( $this, 'overrideI18nLoader' ), 10, 3 );
        }
        $current_theme->parent()->load_textdomain();
    }

    public function overrideI18nLoader( $activate, $domain, $mofile )
    {
        // Don't intercept anything else: Self removing
        remove_filter( current_filter(), __FUNCTION__ );

        // Rebuild the internals of WP_Theme::get_stylesheet_directory() and load_theme_textdomain()
        $theme  = $this->getTheme();
        $path   = trailingslashit( $theme->get_theme_root() ).$theme->get_template();
        $locale = apply_filters( 'theme_locale', get_locale(), $domain );

        load_textdomain( $domain, "{$path}/{$locale}.mo" );

        // Return true to abort further attempts
        return true;
    }
}
Kaiser
quelle
Ich habe eine Antwort geschrieben, als ich über eine neue Antwort informiert wurde. In meiner Antwort schrieb ich, um die übergeordnete Textdomäne in zu laden functions.php. Ihre Antwort ist großartig, steht aber nicht in Konflikt mit einem untergeordneten Thema, über das die eigene untergeordnete Textdomäne definiert wird load_child_theme_textdomain? Allerdings +1 sicher.
gmazzap
@ GM Danke. Nein, es sollte diesen Anruf nicht abfangen. Es gibt keine Verbindung zwischen diesen. Aber ich fand einige andere Fehler und interessante (oder mit anderen Worten: irgendwie dumme) Dinge, die hinter den Kulissen passieren.
Kaiser
1
Gute Arbeit. Traurig ist nicht wieder +1 möglich!
gmazzap
3

Standardmäßig funktioniert dies sofort. Wenn das übergeordnete Thema eine Übersetzung anbietet, übernimmt das untergeordnete Thema diese.

Wenn es nicht funktioniert, stimmt etwas nicht. Dies war in meinem Fall, hier ist, wie ich das Problem behoben habe:

  1. Ich habe das übergeordnete Thema aktiviert, um festzustellen, ob die Übersetzung dort funktioniert hat - dies war nicht der Fall.
  2. Dann habe ich das Debug Translations Plugin installiert , um zu erfahren, welche Sprachdateien geladen werden sollen.
  3. Ich habe dann eine Xdebug-Debug-Sitzung ( ?XDEBUG_SESSION_START=1) gestartet und die als fehlerhaft gemeldete Ladeposition überprüft, indem ich dort einen Haltepunkt platziert und darauf getreten habe.

Es stellte sich dann heraus, dass Wordpress nach einem anderen Dateinamen suchte. Ich habe den Dateinamen korrigiert und es hat dann funktioniert.

Moral der Geschichte: Sprachdateien in Themen sollten, wie de_DE.moin meinem Fall, nur mit dem lokalen Namen benannt werden.


Fehlerhaft:

+ wp-content
+--+ themes
|  +--+ child-theme
|  |  `--- style.css
.  .    ...
|  `--+ twentytwelve
|     +--+ languages
|     |  `--- twentytwelve-de_DE.mo    <<<
.    ...

Arbeiten:

+ wp-content
+--+ themes
|  +--+ child-theme
|  |  `--- style.css
.  .    ...
|  `--+ twentytwelve
|     +--+ languages
|     |  `--- de_DE.mo    <<<
.    ...
hakre
quelle
1
Ich habe versucht, dreiundzwanzig Themen zu erstellen, und habe sofort gearbeitet (lokalisierte italienische Version, heruntergeladen von it.wordpress.org). Mit zwölfundzwanzig nicht. Und mir scheint, dass zwei Themen Übersetzungen auf die gleiche Weise implementieren (.po / .mo-Dateien im wp-content / Languages ​​/ theme und mit den Namen Twentythirteen-it_IT.po / .mo und Twentytwelve-it_IT.po / .mo). Ich kann nicht verstehen warum.
gmazzap
@ GM: Oh, das ist interessantes Feedback, das Sie hier notieren. Vielleicht zeigt meine bisherige Antwort nicht die ganze Geschichte. Ich habe jetzt die Dateispeicherorte hinzugefügt, um klarer zu machen, wo mein Fehler war, was wahrscheinlich hilft, Dinge zu vergleichen.
hakre