【问题标题】:Override a WordPress plugin translation file on load加载时覆盖 WordPress 插件翻译文件
【发布时间】:2018-08-07 02:16:55
【问题描述】:

我正在使用带有插件 The Events Calendar 的法语版 WordPress。

这个插件附带一个捆绑的法语翻译,但它有一些错误。我想修复它们,但替换原始文件是个坏主意,因为它将被下一次更新替换。我联系了开发者以提交修复,但可能需要一些时间。

与此同时,我想从我的模板目录中加载一个副本。我已经尝试了多种方法,例如:

load_plugin_textdomain( 'tribe-events-calendar', get_template_directory() . '/languages' );

或与

add_filter('override_load_textdomain', …)

在我的functions.php 中,但它似乎不起作用。我唯一能做的就是禁用原始翻译文件的加载。

有没有办法在加载时替换插件翻译文件?我也使用 WPML,但在“使用 .mo 文件翻译”模式下而不是在“使用 WPML 翻译”模式下,所以我无法即时更改插件翻译。也许 WPML 可以加载我自己翻译的活动日历?

【问题讨论】:

    标签: wordpress wpml


    【解决方案1】:

    你可以在你的functions.php主题文件中添加这几行

    $text_domain = 'the-events-calendar';
    $original_language_file = ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'the-events-calendar' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'the-events-calendar-fr_FR.mo';
    $override_language_file = ABSPATH . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'your-own-theme' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'the-events-calendar-fr_FR.override.mo'; 
    
    // Unload the translation for the text domain of the plugin
    unload_textdomain($text_domain);
    // Load first the override file
    load_textdomain($text_domain, $override_language_file );
    // Then load the original translation file
    load_textdomain($text_domain, $original_language_file );
    

    您必须将这两个文件变量替换为实际的语言文件。

    但我们假设法语语言文件位于插件语言文件夹中,而您的覆盖语言文件位于语言主题文件夹中。

    这个想法是:

    • 卸载已经被 WP 自动加载的语言
    • 首先加载您的覆盖文件。首先加载它很重要,因为当您为此文本域加载另一个语言文件时,将跳过已经定义的翻译(请参阅WP core)。
    • 加载原始翻译文件,这实际上将加载覆盖文件的所有未翻译字符串。

    这仅适用于已编译的 mo 文件。

    您只能将要覆盖的几个字符串添加到覆盖文件中。

    【讨论】:

    • 这应该是公认的答案。我相信这是 Wordpress 的方式
    • 优秀。你应该摆脱“$path”。在最后一行
    • @ChristerFernstrom 你是对的,我刚刚删除了它
    • 这将覆盖所有语言。
    • 这里是简短的解决方案。最好使用 load_textdomain 钩子来检查加载的文件是否是你要覆盖的文件
    【解决方案2】:

    我是 Transposh 插件的作者,

    您的答案实际上在以下四个过滤器中:

       add_filter('gettext', ......, 3);
       add_filter('gettext_with_context', ......, 3);
       add_filter('ngettext', ......, 4);
       add_filter('ngettext_with_context', ....., 4);
    

    (自然需要加上函数和优先级,而不是.....)

    这些函数将获取字符串和域,您可以使用它们执行以下功能:

    function gettext_filter($translation, $orig, $domain) {
        if ($domain == 'plugin_domain') {
            if ($orig == 'some text') {
                return "some translation";
            }
        }
        return $translation;
    }
    

    【讨论】:

    • 其实我想替换整个翻译文件,而不是手动替换每个字符串。无论如何,谢谢。
    • 我正在为另一个插件寻找相同的插件。这个解决方案很方便,但从性能角度来看似乎很差。添加一个过滤器来为每个对 gettext 的调用运行一个函数,并进行条件检查以查看在给定时刻处理的字符串是否会因任何更改而恰好是我们感兴趣的字符串。这需要gettext_filter 函数可能会在每个页面加载时运行数百次,只是为了翻译一个字符串,而该字符串只会出现一小部分时间。如果您想优化繁忙的网站以提高性能,这可能不是一件好事。
    • 更好的方法是覆盖整个 .mo 文件,就像许多插件模板允许通过简单地在主题根目录中放置替代版本来覆盖模板一样。
    • 看来正确的做法实际上是覆盖整个 mo 文件。我还没有对此进行太多工作,我不确定它是否需要相关插件的特定支持,但请查看此线程以获得一些指导:wordpress.stackexchange.com/questions/30555/…
    • 但请注意,替换整个 mo 文件意味着您根本不会获得插件翻译的任何更新,即使源 PHP 中的字符串发生更改。如果插件更改了其中一个字符串,您将不会在自己的文件中对其进行翻译。
    【解决方案3】:

    此解决方案使用 wordpress 的自动加载器来覆盖插件,不需要额外的编程逻辑,而是让 CMS 来进行覆盖。

    假设您要翻译一个名为my-plugin 的插件。一个正确构建的插件将在目录wp-content/languages/plugins/ 中有两个翻译文件,分别称为my-plugin-fr_FR.pomy-plugin-fr_FR.mo

    如果你的插件有这个结构,下面的步骤会覆盖翻译,如果没有,你可以试试看:

    1. 将上面提到的.po和.mo文件复制到wp-content/languages/my-plugin目录下。如果该目录不存在,请创建它。
    2. 根据需要编辑翻译文件并保存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-07
      • 2015-02-11
      • 2018-10-09
      • 2019-01-27
      • 2017-02-27
      • 1970-01-01
      • 2017-11-02
      • 2021-04-11
      相关资源
      最近更新 更多