問題描述

只要創建一個 child-theme 就足夠了 – 讓我們在技術上説沒有添加任何其他東西,但最低限度的 style.css – 為 child-theme 自動使用 parent-theme 的翻譯?

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

二十二主題有標準的語言翻譯文件。

如果這不會在我的網站上自動發生,那麼開始 trouble-shooting 的翻譯是什麼?

最佳解決方案

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?

基本上,答案是 NO,… 但… 有一個選擇:

添加一個 mu-plugin 。

這個 (MU-) 插件有幾件事情:

  1. 它以 20 的優先級掛接到 after_setup_theme 中,假設父文本域/i18n .mo 文件以正確掛鈎的默認優先級正確加載。

  2. 然後它檢索 instanceof WP_Theme – 在這種情況下是兒童主題。

  3. 然後它檢查是否真的有一個孩子主題在使用。

  4. 如果這是真的,那麼它只會從父文件加載文本域。

實際上很容易,因為核心類對我們進行了大量的檢查:它檢索了父主題的另一個 WP_Theme 實例。然後檢查 TextDomain 標題是否已設置,使用:$current_theme->get( 'TextDomain' ); 。因此,這個遊戲有一個約定:這個插件只能工作,如果父主題得到了一個 Text Domain 和 (!) 一個 Domain Path 標題集。

<?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();
}

現在這裏出現了問題:由 core 提供的默認/標準的二十*主題不 (!) 具有 Domain Path 標題條目。這是我們必須立即修復的東西,因為 load_theme_textdomain()其他搜索不在父主題文件夾中的翻譯文件,但是

  • 首先在子主題文件夾:get_stylesheet_directory().WP_Theme::get( 'DomainPath' ),這意味着 (A)Domain Path 需要設置,它需要以斜槓為前綴:/

  • 然後在子主題文件夾中:`get_stylesheet_directory() 。’/languages’ 。

  • 並在 WP_LANGUAGE_DIR.'/themes'目錄中。

注意:我猜這只是”backwards compatibility” 永遠不會被修復的錯誤,換句話説,這意味着有一個錯誤,但可能已經有開發人員在使用它了。 :P

那還有另外一個問題。 WP_Theme 類方法 load_textdomain()內部通過 $pathload_theme_textdomain()。而這個參數是 $this->get_stylesheet_directory()。此方法返回 $this->theme_root . '/' . $this->stylesheet 。所以這個功能實際上會很好,但是它只是簡單地調用 get_stylesheet_directory()的內部替換 (這是可以過濾的) 。人們現在可以想想

“Hey! The class implements ArrayAccess! So simply set the missing array key of Domain Path!”

錯誤。所有類的屬性都標記為 private,無法訪問。

那你可能會想

“Why not simply extend the WP_Theme class and define a set() Method so we can manually set the missing header entries?”

錯誤。該類本身是 final,不可擴展。

結果:我們留下了什麼 load_theme_textdomain() – 呼叫鏈中的最後一個功能 – 提供給我們。現在我們收到一個更大的插件來攔截 load_theme_textdomain()調用來加載正確的文件。為了不打擾其他 i18n 文件加載,它會立即從過濾器中刪除回調,以保持您的環境整潔。

<?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;
    }
}

次佳解決方案

默認情況下,這只是開箱即用。如果父主題提供翻譯,child-theme 將會結束。

如果它不工作的東西是錯誤的。這是在我的情況,這裏是我做了 trouble-shoot:

  1. 我激活了父主題,看看翻譯是否在那裏工作 – 沒有。

  2. 然後我安裝了 Debug Translations 插件來瞭解哪些語言文件被加載。

  3. 然後,我啓動了一個 Xdebug 調試會話 (?XDEBUG_SESSION_START=1),並通過在其中放置一個斷點來驗證報告已被破壞的加載位置。

然後,結果是 Wordpress 正在尋找一個不同的 file-name 。我更正了文件名,然後工作。

故事的士氣:主題中的語言文件應該只用本地命名,就像我的情況下的 de_DE.mo


故障:

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

加工:

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

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。