Typecho DIY多国语言支持教程(完整版)
在此将会记录笔者为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