在此将会记录笔者为Typecho添加完整多语言支持的过程。

一个完整的多国语言功能包括:

  • 随浏览器语言切换语言(此前博客已经实现)
  • 用户可根据实际情况手动切换显示语言
  • 文章内容多国语言适配(一篇文章, 多种语言可供切换)

注意:本文所述适用于Typecho 1.1, 其他版本应该不会有太大变化。


一、随浏览器语言切换语言

原理:
typecho原生自带了翻译功能, 但不支持随客户端语言自动切换。 因此获取客户端语言, 并替换原生翻译功能所调用的翻译文件即可。

注意:需要先开启Typecho原生的多国语功能。
关于原生的翻译功能 —> https://www.typechodev.com/case/typecho-language.html

更改Typecho根目录下/var/Typecho/I18n.php里的77行:

/**
* 初始化语言文件
*
* @access private
*/
private static function init()
{
/** GetText支持 */
if (false === self::$_loaded && self::$_lang && file_exists(self::$_lang)) {
self::$_loaded = new Typecho_I18n_GetTextMulti(self::$_lang);
}
}

更改为如下:

private static function init()
    {   
        /** 检查客户端语言 */
        if(!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
            $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
                $langConfig = substr($lang,0,5);
            if(preg_match("/zh/i",$lang)){
                $langConfig = "zh_TW";
            }
            elseif(preg_match("/zh-cn/i",$lang)){
                $lang = "zh_CN";
            }
            else{
                 $langConfig = "en_US";
            }
        }
        else{
            $langConfig = 'en_US';
        }

        /**检查是否有自定义语言 */
        if(Typecho_Cookie::get('__earthlog_autoLang')){
            $langConfig = Typecho_Cookie::get('__earthlog_autoLang');
        }
        else{
            Typecho_Cookie::set('__earthlog_autoLang', $langConfig);
        }
       
        $dir = defined('__TYPECHO_LANG_DIR__') ? __TYPECHO_LANG_DIR__ : __TYPECHO_ROOT_DIR__ . '/usr/langs';
        $langConfig = ($dir . '/' . $langConfig.".mo");

        /** GetText支持 */
        if (false === self::$_loaded && $langConfig && file_exists($langConfig)) {
            self::$_loaded = new Typecho_I18n_GetTextMulti($langConfig);
        }
    }

注意, 这里替换成的代码和前一篇博客中的略有不同。


二、根据实际情况手动切换显示语言

原理:

  • 通过COOKIE储存用户设置, 再载入时读取
  • 用户切换语言后redirect回原网页

设置COOKIE - /admin/autoLang.php

Typecho没有这个文件, 需手动创建。

<?php
if (!defined('__DIR__')) {
    define('__DIR__', dirname(__FILE__));
}

define('__TYPECHO_ADMIN__', true);

/** 载入配置文件 */
if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once __DIR__ . '/../config.inc.php') {
    file_exists(__DIR__ . '/../install.php') ? header('Location: ../install.php') : print('Missing Config File');
    exit;
}

/** 初始化组件 */
Typecho_Widget::widget('Widget_Init');

/** 注册一个初始化插件 */
Typecho_Plugin::factory('admin/common.php')->begin();

Typecho_Widget::widget('Widget_Options')->to($options);
Typecho_Widget::widget('Widget_User')->to($user);
Typecho_Widget::widget('Widget_Security')->to($security);
Typecho_Widget::widget('Widget_Menu')->to($menu);

/** 初始化上下文 */
$request = $options->request;
$response = $options->response;

//localhost/earthlog/admin/autoLang.php?setLang=en_US
Typecho_Cookie::set('__earthlog_autoLang', $_GET['setLang']);
$response->redirect($_GET['redirect']);
?>

建议添加后测试一下:

浏览器访问:

http://{你的域名/IP}/admin/autoLang.php?setLang=en_US&redirect=http://{你的域名/IP}

如果没有报错, 并且回到了首页, 即没问题。

将一下代码找到适当位置, 并添加到你的主题里的sidebar.php中:

<?php $here = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; ?>
<a href="http://localhost/earthlog/admin/autoLang.php?setLang=en_US&redirect=<?php echo $here; ?>">English</a>
<a href="http://localhost/earthlog/admin/autoLang.php?setLang=zh_CN&redirect=<?php echo $here; ?>">简体中文</a>
<a href="http://localhost/earthlog/admin/autoLang.php?setLang=zh_TW&redirect=<?php echo $here; ?>">繁體中文</a>

这是手动切换语言的入口。


三、文章内容多国语言适配(一篇文章, 多种语言可供切换)

原理:
通过再写文章/页面时同时写三种语言, 再在不同语言之间添加表示告诉程序这是什么语言即可。
为了不出现意外, 我们尽可能的从主题上入手。

主题编辑 - function.php(/usr/{主题名}/function.php):
这该文件的末尾添加如下函数(无需改动其他):

function getLang($content, $lang){
    $pa = '%@'.$lang.'.*?@(.*?)@/'.$lang.'@%si';
    preg_match_all($pa,$content,$match);
    try{
        //return str_replace("@$lang@<br>" ,"" ,$match[0][0]);
        //return $match[1][0];
        return(str_replace("@/$lang@" , "",str_replace("@$lang@" , "",str_replace("@$lang@<br>" ,"" ,$match[0][0]))));
    }
    catch(Exception $e){
        return(False);
    }
}

function _en($content){  
    print('<div style="
    border-style: solid;
    border-width: 1px;
    display: block;
    font-size: 0.81rem;
    font-weight: normal;
    margin-bottom: 1.25rem;
    padding: 0.875rem 1.5rem 0.875rem 0.875rem;
    position: relative;
    transition: opacity 300ms ease-out;
    border-color: #222;
    ">');
    print($content);
    print("</div>");
}

function _et($content, $needNotice = False){
    try{
        /** 检查客户端语言 */
        if(!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
            $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
                $langConfig = substr($lang,0,5);
            if(preg_match("/zh/i",$lang)){
                $langConfig = "zh_TW";
            }
            elseif(preg_match("/zh-cn/i",$lang)){
                $lang = "zh_CN";
            }
            else{
                 $langConfig = "en_US";
            }
        }
        else{
            $langConfig = 'en_US';
        }

        /**检查是否有自定义语言 */
        if(Typecho_Cookie::get('__earthlog_autoLang')){
            $langConfig = Typecho_Cookie::get('__earthlog_autoLang');
        }
        else{
            Typecho_Cookie::set('__earthlog_autoLang', $langConfig);
        }

        
        if($langConfig == "zh_CN"){
            $langConfig = "zh_CN";
            $alternation = "zh_TW";
            $langNotice = array(
                0 => "<div class='tag-links'>已根据浏览器语言为您展示简体中文。</div>",
                1 => "<div class='tag-links'>很抱歉, 这篇文章没有提供简中内容。 我们将尝试为您显示繁中译文。</div>",
                2 => "<div class='tag-links'>很抱歉, 这篇文章没有提供简中内容。 我们将会为您显示英文译文。</div>",
                3 => "<div class='tag-links'>很抱歉, 这个页面没有启用多语言支持。</div>"
            );
        }
        elseif($langConfig == "zh_TW"){
            $langConfig = "zh_TW";
            $alternation = "zh_CN";
            $langNotice = array(
                0 => "<div class='tag-links'>已按照用戶端語言爲您顯示繁中譯文。</div>",
                1 => "<div class='tag-links'>糟糕, 本文不提供繁體中文譯文。 在此我們將試著展示简体中文譯文。</div>", 
                2 => "<div class='tag-links'>糟糕, 本文不提供繁體中文譯文。 在此我們將會爲您展示英文譯文。</div>", 
                3 => "<div class='tag-links'>抱歉, 此頁面尚未啓用多語言服務。</div>"
            );
        }
        else{
            $langConfig = "en_US";
            $alternation = "none";
            $langNotice = array(
                0 => "<div class='tag-links'>We are showing you a translated content by identified your browser.</div>",
                1 => "" ,
                2 => "" ,
                3 => "<div class='tag-links'>We apologize that the translated content is not provided to this page.</div>"
            );
        }

        $trans = getLang($content, $langConfig);
        /**如果不支持客户端语言 */
        if($trans == False){
            $trans = getLang($content, $alternation);

            /**如果不支持备选语言 */
            if($trans == False){
                $trans = getLang($content, "en_US");

                /**如果不支持英语 */
                if($trans == False){
                    if($needNotice == True){
                        _en($langNotice[3]);
                    }
                    print($content);
                }
                else{
                    if($needNotice == True){
                        _en($langNotice[2]);
                    }
                    print($trans);
                }
            }
            else{
                if($needNotice == True){
                    _en($langNotice[1]);
                }
                print($trans);
            }
        }
        else{
            if($needNotice == True){
                _en($langNotice[0]);
            }
            print($trans);
        }
    }
    catch(Exception $e){
        print($content);
            if($needNotice == True){
        print("*It seems that the translated verison of this content is not supported.");
            }
    }
}

保存, 关闭。

主题编辑 -> post.php(/usr/{主题名}/post.php)

将所有的

<?php $this->content(); ?>

改为:

<?php _et($this->content, True); ?>

记住, 是所有!

主题编辑 -> page.php(/usr/{主题名}/page.php)
将所有的

<?php $this->content(); ?>

改为:

<?php _et($this->content, True); ?>

主题编辑 -> index.php(/usr/{主题名}/index.php)

将所有的

<?php $this->content(); ?>

改为:

<?php _et($this->content); ?>
//注意, 这里和前面不一样了, 没有后面那个True。

主题编辑 -> archive.php(/usr/{主题名}/archive.php)
将所有的

<?php $this->content(); ?>

改为:

<?php _et($this->content); ?>
//注意, 这里和前面不一样了, 没有后面那个True。

四, 结尾

到现在, 其实这已经完成了整个多语言支持的搭建。
文章/独立页面的多语言支持需要所有文章使用一下模板编辑:

@zh_CN@
这里输入文章内容-简体中文
@/zh_CN@

@en_US@
Here to input Article content-English
@/en_US@

@zh_TW@
這裏錄入文章内容-繁體中文
@/zh_TW@                     

@NOTICE@
修改引号里的内容, 不要改动其他的。 如果不翻译就把所有东西删掉直接写, 如果其中一个语言不翻译就删掉那行就可。
@/NOTICE@

当然, 可以修改以下文件使这个模板在每次新建文章/页面使显示在编辑器中:

修改/admin/write-post.php 40行:

<p>
                        <label for="text" class="sr-only"><?php _e('文章内容'); ?></label>
                        <textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono"><?php echo htmlspecialchars($post->text); ?></textarea>
                    </p>

修改为:

<p>
                        <label for="text" class="sr-only"><?php _e('文章内容'); ?></label>
                        <textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono">
<?php 
if(($page->text) != ""){
    print htmlspecialchars($page->text);
}
else{

print("@zh_CN@
文章内容-简体中文
@/zh_CN@

@en_US@
Article content-English
@/en_US@

@zh_TW@
文章内容-繁體中文
@/zh_TW@                     

@NOTICE@
修改引号里的内容, 不要改动其他的。 如果不翻译就把所有东西删掉直接写, 如果其中一个语言不翻译就删掉那行就可。
@/NOTICE@");
}
?>
</textarea>

修改/admin/write-page.php 36行:

<p>
                        <label for="text" class="sr-only"><?php _e('页面内容'); ?></label>
                        <textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono"><?php echo htmlspecialchars($page->text); ?>
</textarea>
                    </p>

修改为:

<p>
                        <label for="text" class="sr-only"><?php _e('页面内容'); ?></label>
                        <textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono">
<?php 
if(($page->text) != ""){
    print htmlspecialchars($page->text);
}
else{

print("@zh_CN@
文章内容-简体中文
@/zh_CN@

@en_US@
Article content-English
@/en_US@

@zh_TW@
文章内容-繁體中文
@/zh_TW@                     

@NOTICE@
修改引号里的内容, 不要改动其他的。 如果不翻译就把所有东西删掉直接写, 如果其中一个语言不翻译就删掉那行就可。
@/NOTICE@");
}
?>
</textarea>
                    </p>

©版权: https://huawenzixun.com/post/2756.html

标签: 技术

你可能感兴趣

添加新评论