网站一般会有一个语言标记,亲如果右键查看本页的html源代码,会在前两行看到类似下面这样的内容,这段代码里涉及到了一个lang 属性,这个属性是 HTML 中用于声明网页或元素内容语言的重要属性,它对网页的可访问性、SEO 和用户体验都有重要影响。在typecho里,可以通过它来影响站点的语言展现。
<!DOCTYPE html>
<html lang="zh-CN">
先说结论
echo _t('站点 LOGO 地址');
typecho里的多语言设置一般会用到上面这个函数,如果没有多语言需求,无论是单一的英文或者中文站点,我们都可以直接输出字符串,想实现中文主题就直接输出中文:
echo '站点 LOGO 地址';
而英文主题就直接输出英文:
echo 'site logo';
完结撒花~~
语言设置参数的提取与修改
获取值
在主题的页面展示部分,我们可以通过 $this->options->lang
来获取typecho站点的语言设置,而在后台,如果无法通过前一个命令获取到值,比如在functions.php文件里想提取这个值的时候,我们需要使用 Helper::options()->lang
这样的形式。
修改值
正常情况,对于站点的语言设置,我们可以去后台的设置项里直接修改,如果希望利用代码修改的,可以参考下方的代码:
function changeLanguageToEnglish() {
$db = Typecho_Db::get();
$db->query($db->update('table.options')
->rows(array('value' => 'en-US'))
->where('name = ?', 'lang'));
// 可选:清除缓存,使更改立即生效
if (method_exists('Typecho_Widget', 'destory')) {
Typecho_Widget::destory('Widget_Options');
}
}
// 调用函数(例如在插件激活时或主题初始化时)
changeLanguageToEnglish();
被隐藏的语言设置项
既然是多语言,那我们提取到的必然是一个可变的值,但博主打赌,即便亲翻遍了基本设置页所有项,也找不到语言设置的按钮。显示语言设置项需要一个很大的前摇;
首先需要进入typecho安装文件夹(注意:不是主题文件夹)根目录下的usr文件夹内,新建一个名为“langs”的文件夹,然后把对应语言(比如 en-US.mo)文件放进去;
关于.po
与.mo
文件,这是两种专用于翻译领域的文件格式,虽然看着都是陌生后缀,实际操作一遍下来,最麻烦的步骤反而是下载它们的专用编辑器“Poedit”。
翻译实操
比如以下的代码,已经提前利用 _t()
函数对需要翻译的语句做了处理,现在我们可以直接把它扔给deepseek等ai工具,
if (isset($_POST['type'])) {
$value = $db->fetchRow($db->select()->from('table.options')->where('name = ?', 'theme:' . $name))['value'];
if ($_POST["type"] == "backup") {
$backupData = [
'backup_time' => date('Y-m-d H:i:s'),
'theme' => $name,
'settings' => unserialize($value)
];
$jsonData = json_encode($backupData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$filename = $backupDir . 'theme_' . $name . '_backup.json';
if (file_put_contents($filename, $jsonData)) {
?>
<script>alert("<?php echo _t('主题设置已备份!'); ?>");</script>
<?php
} else {
?>
<script>alert("<?php echo _t('备份失败,请检查 backup 目录权限!'); ?>");</script>
<?php
}
}
if ($_POST["type"] == "recovery") {
$backupFile = $backupDir . 'theme_' . $name . '_backup.json';
if (file_exists($backupFile)) {
$backupContent = file_get_contents($backupFile);
$backupData = json_decode($backupContent, true);
if ($backupData && isset($backupData['settings'])) {
$serializedSettings = serialize($backupData['settings']);
$db->query($db->update('table.options')->rows(array('value' => $serializedSettings))->where('name = ?', 'theme:' . $name));
?>
<script>
alert("<?php echo _t('已从备份文件恢复主题设置!'); ?>");
window.location.href="<?php Helper::options()->adminUrl('options-theme.php');?>";
</script>
<?php
} else {
?>
<script>
alert("<?php echo _t('备份文件解析失败,文件可能已损坏!'); ?>");
</script>
<?php
}
} else {
?>
<script>
alert("<?php echo _t('未能找到备份文件,无法恢复!'); ?>");
</script>
<?php
}
}
if ($_POST["type"] == "download") {
$backupFile = $backupDir . 'theme_' . $name . '_backup.json';
ob_clean();
ob_start();
if (file_exists($backupFile)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="theme_' . $name . '_backup.json"');
header('Content-Length: ' . filesize($backupFile));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
ob_end_flush();
readfile($backupFile);
exit;
} else {
?>
<script>
alert("没有找到可下载的备份文件!");
</script>
exit;
<?php
}
}
}
整理好的文档内容如下,将其复制后保存为 en_US.po
文件。
# Typecho Theme Backup Translations
# Copyright (C) 2023 Your Theme Name
msgid ""
msgstr ""
"Project-Id-Version: Your Theme Backup\n"
"POT-Creation-Date: 2023-11-20 10:00+0800\n"
"PO-Revision-Date: 2023-11-20 10:00+0800\n"
"Last-Translator: Your Name <your@email.com>\n"
"Language-Team: Your Team <team@email.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
msgid "主题设置已备份!"
msgstr "Theme settings have been backed up!"
msgid "备份失败,请检查 backup 目录权限!"
msgstr "Backup failed, please check backup directory permissions!"
msgid "已从备份文件恢复主题设置!"
msgstr "Theme settings have been restored from backup!"
msgid "备份文件解析失败,文件可能已损坏!"
msgstr "Failed to parse backup file, the file may be corrupted!"
msgid "未能找到备份文件,无法恢复!"
msgstr "Backup file not found, unable to restore!"
msgid "没有找到可下载的备份文件!"
msgstr "No downloadable backup file found!"
电脑上安装好Poedit软件,用它来打开准备好的 po 文件,点击保存后会自动生成同名 mo 文件,用这个mo文件去就可以进行翻译测试工作了。在后台设置页将语言设置修改为英文(en_US),保存后尝试 "_t()" 输出翻译前的中文,看看会不会被自动转为英文吧。
复制文档内容并另存为 po 文件的操作尽量使用更专业的编辑器(sumlime、notepad++等),避免使用windows自带的那个,可能会引发不必要的错误。
语言包能否直接放主题里呢
安装了一个主题还不够,还得去主题文件夹新建文件夹,上传文件,听听也觉得头大,那么问题来了,能否把语言包直接放主题里呢,答案是可以的。
use Typecho\I18n;
define( 'AUG_THEME_DIR' , __DIR__ );
I18n::setLang(AUG_THEME_DIR . '/langs/en-US.mo');
利用上面的语句,我们可以把语言包直接放在主题根目录的langs文件里读取,遗憾的是,如果这么做了,那么设置里那个隐藏的多语言选项就不可见了。
I18n::setLang(AUG_THEME_DIR . '/langs/' . Helper::options()->Auglangs . '.mo');
博主的解决方案是在主题后台设置项里增加一个语言选项,供用户在主题设置页面设置语言项目,但这样一来,就跳过了typecho官方渠道参数,后期可能会导致一些不便,容博主碰到相关问题再进行补充吧。