核心思路
无论采用哪种方法,实现双语网站的核心思路都是一致的:
- 语言切换:提供一种方式让用户在中文和英文之间切换,通常是通过URL中的参数来标识当前语言,
- 中文:
http://www.yoursite.com/ - 英文:
http://www.yoursite.com/en/或http://www.yoursite.com/?lang=en
- 中文:
- 内容关联:建立一个机制,将中文内容和英文内容关联起来,这样,当用户切换语言时,系统能找到对应的内容。
- 模板适配:根据当前语言状态,在模板中调用对应语言的内容。
使用栏目别名(最常用,推荐)
这是最主流、最符合织梦CMS设计思想的方法,尤其适合内容结构不经常变更的网站。
实现原理
为同一个栏目创建两个版本:一个中文栏目,一个英文栏目,然后通过栏目的 typeid 和 en typeid(或其他自定义字段)来建立关联,通过URL中的路径(如 /en/)来判断当前语言,并动态加载对应的栏目ID。
详细步骤
栏目结构设计
- 在后台“栏目管理”中,创建所有需要的栏目。
- 示例:
- 创建一个顶级栏目“首页” (Home),ID假设为
1。 - 创建一个顶级栏目“关于我们” (About Us),ID假设为
2。 - 再创建一个英文版的顶级栏目“About Us”,ID假设为
3。
- 创建一个顶级栏目“首页” (Home),ID假设为
设置栏目别名
- 在“栏目管理”中,编辑每个中文栏目。
- 在“栏目别名”或“高级选项”中,填写其对应的英文栏目ID,在“关于我们”栏目(ID=2)的自定义字段中添加一个字段
en_typeid,并填入3。 - 同样,在英文栏目(ID=3)中添加一个
zh_typeid字段,并填入2。
创建语言切换链接
在网站头部模板(如 head.htm)中,放置语言切换按钮。
<div class="language-switcher">
<a href="{dede:global.cfg_basehost/}/">中文</a>
<a href="{dede:global.cfg_basehost/}/en/">English</a>
</div>
这里我们用URL路径 /en/ 来代表英文。
修改模板,实现动态内容调用 这是最关键的一步,我们需要在模板中判断当前语言,并调用对应栏目的内容。
-
首页模板 (
index.htm): 首页通常是一个聚合页,需要根据语言调用不同栏目的文章列表。{dede:php} // 判断当前语言 $lang = 'zh'; // 默认为中文 if (isset($_GET['lang']) && $_GET['lang'] == 'en') { $lang = 'en'; } // 获取当前栏目的ID,首页通常是1 $typeid = $lang == 'en' ? 3 : 1; // 英文对应栏目ID为3,中文为1 // 将typeid变量传递给dede标签 $GLOBALS['typeid'] = $typeid; {/dede:php} <h1>{dede:field.title/}</h1> <!-- 调用当前语言栏目的文章列表 --> {dede:arclist row="10" titlelen="30"} <li><a href="[field:arcurl/]">[field:title/]</a></li> {/dede:arclist} -
列表页模板 (
list_xxx.htm): 列表页需要根据当前栏目,动态获取其关联的英文或中文栏目ID。{dede:php} // 判断当前语言 $lang = 'zh'; if (isset($_GET['lang']) && $_GET['lang'] == 'en') { $lang = 'en'; } // 获取当前栏目的ID $current_typeid = $GLOBALS['typeid']; // 获取关联的栏目ID if ($lang == 'en') { // 如果是英文,则查询当前栏目的 zh_typeid 字段 $en_typeid = $dsql->GetOne("SELECT zh_typeid FROM `#@__arctype` WHERE id = $current_typeid"); $typeid = $en_typeid['zh_typeid']; } else { // 如果是中文,则查询当前栏目的 en_typeid 字段 $zh_typeid = $dsql->GetOne("SELECT en_typeid FROM `#@__arctype` WHERE id = $current_typeid"); $typeid = $zh_typeid['en_typeid']; } // 将typeid变量传递给dede标签 $GLOBALS['typeid'] = $typeid; {/dede:php} <h1>{dede:field.title/}</h1> <!-- 调用关联栏目的文章列表 --> {dede:arclist row="10" titlelen="30"} <li><a href="[field:arcurl/]">[field:title/]</a></li> {/dede:arclist} -
页 (
article_article.htm):页的逻辑与列表页类似,也需要通过PHP代码找到当前文章对应语言的版本。{dede:php} // 判断当前语言 $lang = 'zh'; if (isset($_GET['lang']) && $_GET['lang'] == 'en') { $lang = 'en'; } // 获取当前文章的栏目ID $current_typeid = $GLOBALS['typeid']; // 获取关联的栏目ID (逻辑同列表页) if ($lang == 'en') { $en_typeid = $dsql->GetOne("SELECT zh_typeid FROM `#@__arctype` WHERE id = $current_typeid"); $typeid = $en_typeid['zh_typeid']; } else { $zh_typeid = $dsql->GetOne("SELECT en_typeid FROM `#@__arctype` WHERE id = $current_typeid"); $typeid = $zh_typeid['en_typeid']; } // 查找同一栏目下,标题(或其他字段)相似的文章作为对应版本 // 这是一个简化的查找逻辑,实际中可能需要更复杂的关联,比如在文章表里加一个关联字段 $arcid = $GLOBALS['arcid']; $query = "SELECT id FROM `#@__archives` WHERE typeid = $typeid AND title LIKE '%".GetOneArc($arcid)['title']."%'"; $row = $dsql->GetOne($query); $related_arcid = $row['id']; // 生成对应语言的文章链接 if ($related_arcid) { $GLOBALS['related_url'] = GetOneArchive($related_arcid)['arcurl']; } {/dede:php} <h1>{dede:field.title/}</h1> <div class="content"> {dede:field.body/} </div> <!-- 添加一个“阅读英文版”或“阅读中文版”的链接 --> {if $related_url} <a href="{$related_url}">Read in {if $lang=='zh'}English{else}中文{/if}</a> {/if}
优点
- SEO友好:每个语言版本都有独立的URL,搜索引擎可以分别索引。
- 结构清晰管理结构清晰,符合织梦CMS原生逻辑。
- 稳定可靠:不依赖第三方插件,长期使用更稳定。
缺点
- 维护成本高需要在后台分别录入和管理,如果内容量大,会非常繁琐。
- URL结构:需要规划好URL路径,避免混乱。
使用自定义字段(适合内容关联性强的情况)
这种方法适合栏目结构完全一致,只是语言不同的网站,它不创建额外的栏目,而是在同一个栏目下为每篇文章添加一个对应语言版本的ID。
实现原理
- 在文章附加表
dede_archives中增加一个自定义字段,en_aid(English Article ID)。 - 发布中文文章时,同时发布或找到对应的英文文章,并将英文文章的ID填入
en_aid字段。 - 在模板中,通过PHP读取当前文章的
en_aid或zh_aid,从而获取关联文章的URL。
步骤
-
后台添加字段:在后台“核心” -> “内容模型管理” -> “普通文章” -> “字段管理”中,添加一个新字段,字段名为
en_aid,数据类型选择“数字”。 -
内容录入:发布一篇文章,然后发布其英文版本,在中文文章的编辑页面,找到
en_aid字段,填入英文文章的ID,反之亦然。 -
模板修改:
- 页:通过
en_aid字段获取关联文章ID,然后生成链接。
{dede:php} $lang = 'zh'; if (isset($_GET['lang']) && $_GET['lang'] == 'en') { $lang = 'en'; } $en_aid = $fields['en_aid']; // 获取当前文章的英文ID $zh_aid = $fields['zh_aid']; // 假设你也添加了zh_aid字段 $related_id = ($lang == 'en') ? $zh_aid : $en_aid; if ($related_id) { $archive = GetOneArchive($related_id); $GLOBALS['related_url'] = $archive['arcurl']; } {/dede:php} <h1>{dede:field.title/}</h1> <div class="content"> {dede:field.body/} </div> {if $related_url} <a href="{$related_url}">Switch to {if $lang=='zh'}English{else}中文{/if}</a> {/if} - 页:通过
优点
- 内容集中:同一主题的不同语言版本在后台可以放在一起管理,方便对照。
- URL简洁:不需要创建多个栏目,URL结构可以更统一。
缺点
- 关联复杂时需要手动关联ID,容易出错。
- 扩展性差:如果需要增加第三种语言,需要修改数据表结构和所有模板。
使用第三方多语言插件
市面上有一些织梦CMS的多语言插件,它们封装了上述逻辑,提供了一套解决方案。
优点
- 开箱即用:对于不想写代码的用户来说,安装插件即可使用。
- 功能集成:通常包含语言切换、URL重写、内容同步等功能。
缺点
- 兼容性风险:插件可能与织梦CMS的特定版本不兼容,升级CMS后可能失效。
- 安全风险:来源不明的插件可能包含后门或漏洞。
- 功能限制:插件的功能是固定的,难以进行深度定制。
- 维护困难:插件作者可能停止更新,出现问题难以自行修复。
不推荐对有一定技术能力的用户依赖插件,除非是功能非常成熟且广受好评的商业插件。
最佳实践方案(推荐)
结合以上分析,我推荐 “方法一:使用栏目别名” 作为最佳实践,并对其进行优化。
-
URL结构:采用 和
/en/的路径结构,这需要配置服务器伪静态规则,将所有/en/开头的请求指向index.php。- Nginx 伪静态规则示例:
rewrite ^/en/(.*)$ /index.php?lang=en&/$1 last; rewrite ^/(.*)$ /index.php?/$1 last;
- Apache 伪静态规则示例 (
.htaccess):<IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^en/(.*)$ index.php?lang=en&/$1 [L] RewriteRule ^(.*)$ index.php?/$1 [L] </IfModule>
- Nginx 伪静态规则示例:
-
模板优化:将语言判断逻辑封装成一个公共函数或变量,避免在每个模板文件中重复编写PHP代码。
- 在
include/extend.func.php文件中添加一个函数:// 获取当前语言对应的栏目ID function getLangTypeid($current_typeid, $lang = 'zh') { global $dsql; $field_name = ($lang == 'en') ? 'zh_typeid' : 'en_typeid'; $query = "SELECT `$field_name` FROM `#@__arctype` WHERE id = $current_typeid"; $row = $dsql->GetOne($query); return $row[$field_name] ? $row[$field_name] : $current_typeid; // 如果找不到,返回当前ID } - 然后在模板中直接调用这个函数,使代码更简洁。
- 在
-
内容管理:
- 为所有需要双语展示的栏目都创建中英文两个版本。
- 使用自定义字段
en_typeid和zh_typeid建立强关联。 - 后台可以创建两个不同的管理员账号,分别负责中文和英文内容的录入,以避免混乱。
-
SEO优化:
-
在每个模板的
<head>部分添加hreflang标签,告诉搜索引擎不同语言版本之间的关系。{dede:php} $current_url = $_SERVER['REQUEST_URI']; $zh_url = 'http://www.yoursite.com' . $current_url; $en_url = 'http://www.yoursite.com/en' . $current_url; if (strpos($current_url, '/en/') !== false) { // 当前是英文页面 $zh_url = str_replace('/en/', '/', $zh_url); echo "<link rel=\"alternate\" hreflang=\"zh-CN\" href=\"$zh_url\" />\n"; echo "<link rel=\"alternate\" hreflang=\"en\" href=\"$en_url\" />\n"; } else { // 当前是中文页面 $en_url = '/en' . $current_url; echo "<link rel=\"alternate\" hreflang=\"zh-CN\" href=\"$zh_url\" />\n"; echo "<link rel=\"alternate\" hreflang=\"en\" href=\"$en_url\" />\n"; } {/dede:php}
-
对于织梦CMS的中英文双语网站,“基于栏目别名的方案” 是最健壮、最灵活且SEO友好的选择,虽然初期设置和模板修改需要一些工作量,但从长远来看,它能为你提供一个稳定、可维护且对搜索引擎友好的多站架构。
