一、多语言网站开发概述
在全球化互联网时代,多语言网站已成为企业拓展国际市场的标配。ThinkPHP 6.x 提供了完善的多语言支持,本教程将带你从零开始实现一个完整的双语(中英文)网站。
我们将实现以下功能:
- 自动检测浏览器语言偏好
- 手动切换语言功能
- 控制器和模板中的多语言处理
- 数据库内容的多语言存储方案
二、环境准备与项目创建
1. 确保已安装PHP 7.1+和Composer
// 创建ThinkPHP 6项目
composer create-project topthink/think tp6-multilang
cd tp6-multilang
2. 配置数据库连接(confg/database.php)
return [
'connections' => [
'mysql' => [
'type' => 'mysql',
'hostname' => '127.0.0.1',
'database' => 'tp6_multilang',
'username' => 'root',
'password' => '',
// 其他配置...
],
],
];
三、多语言配置与实现
1. 基础配置
修改config/lang.php文件:
return [
// 默认语言
'default_lang' => 'zh-cn',
// 允许的语言列表
'allow_lang_list' => ['zh-cn', 'en-us'],
// 多语言自动侦测变量名
'detect_var' => 'lang',
// 使用Cookie记录
'use_cookie' => true,
// 多语言cookie变量
'cookie_var' => 'think_lang',
// 扩展语言包
'extend_list' => [],
// Accept-Language转义为对应语言包名称
'accept_language' => [
'zh-hans-cn' => 'zh-cn',
'en-us' => 'en-us'
],
// 是否支持语言分组
'allow_group' => false,
];
2. 创建语言包文件
在app/lang目录下创建两个语言目录:zh-cn和en-us
创建公共语言文件app/lang/zh-cn.php:
return [
'welcome' => '欢迎使用ThinkPHP',
'home' => '首页',
'about' => '关于我们',
'contact' => '联系我们',
'switch_lang' => '切换语言',
'current_lang' => '当前语言:中文',
];
创建英文版本app/lang/en-us.php:
return [
'welcome' => 'Welcome to ThinkPHP',
'home' => 'Home',
'about' => 'About Us',
'contact' => 'Contact',
'switch_lang' => 'Switch Language',
'current_lang' => 'Current Language: English',
];
四、控制器与模板实现
1. 创建基础控制器
创建app/controller/Index.php:
<?php
namespace appcontroller;
use thinkfacadeLang;
use thinkfacadeView;
class Index
{
public function index()
{
// 获取当前语言
$currentLang = Lang::getLangSet();
// 传递到模板
View::assign([
'lang' => $currentLang,
'title' => Lang::get('welcome')
]);
return View::fetch('index');
}
// 切换语言
public function switchLang($lang)
{
if (in_array($lang, config('lang.allow_lang_list'))) {
// 设置语言
cookie('think_lang', $lang, 3600 * 24 * 365);
}
return redirect(url('index/index'));
}
}
2. 创建模板文件
创建app/view/index/index.html:
<!DOCTYPE html>
<html lang="<?php echo $lang ?>">
<head>
<meta charset="UTF-8">
<title><?php echo $title ?></title>
</head>
<body>
<h1><?php echo $title ?></h1>
<nav>
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><?php echo lang('home') ?></a> |
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><?php echo lang('about') ?></a> |
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><?php echo lang('contact') ?></a>
</nav>
<p><?php echo lang('current_lang') ?></p>
<div>
<a href="<?php echo url('index/switchLang', ['lang' => 'zh-cn']) ?>" rel="external nofollow" >中文</a> |
<a href="<?php echo url('index/switchLang', ['lang' => 'en-us']) ?>" rel="external nofollow" >English</a>
</div>
</body>
</html>
五、数据库内容多语言处理
1. 创建多语言数据表
对于需要多语言的内容,我们通常有两种设计方案:
方案一:字段后缀法 – 适合字段较少的情况
CREATE TABLE `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title_zh` varchar(255) DEFAULT NULL COMMENT '中文标题',
`title_en` varchar(255) DEFAULT NULL COMMENT '英文标题',
`content_zh` text COMMENT '中文内容',
`content_en` text COMMENT '英文内容',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
方案二:关联表法 – 适合复杂多语言需求
-- 主表
CREATE TABLE `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 多语言内容表
CREATE TABLE `article_langs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`article_id` int(11) DEFAULT NULL,
`lang` varchar(10) DEFAULT NULL COMMENT '语言标识',
`title` varchar(255) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`),
KEY `article_id` (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 模型实现
创建app/model/Article.php:
<?php
namespace appmodel;
use thinkModel;
class Article extends Model
{
// 方案一:字段后缀法的获取器
public function getTitleAttr($value, $data)
{
$lang = request()->lang ?? 'zh';
$field = 'title_' . $lang;
return $data[$field] ?? $value;
}
// 方案二:关联表法
public function langs()
{
return $this->hasMany(ArticleLang::class);
}
// 获取当前语言的内容
public function getCurrentLangContent()
{
$lang = request()->lang ?? 'zh-cn';
return $this->langs()->where('lang', $lang)->find();
}
}
六、高级功能扩展
1. 中间件自动检测语言
创建app/middleware/DetectLanguage.php:
<?php
namespace appmiddleware;
use thinkfacadeLang;
class DetectLanguage
{
public function handle($request, Closure $next)
{
// 1. 检查是否有手动设置的语言
$lang = $request->param('lang');
// 2. 检查cookie中的语言设置
if (empty($lang)) {
$lang = cookie('think_lang');
}
// 3. 自动检测浏览器语言
if (empty($lang)) {
$acceptLang = $request->header('accept-language');
if ($acceptLang) {
$langs = explode(',', $acceptLang);
$lang = strtolower(substr($langs[0], 0, 2));
// 映射到支持的语言
if ($lang == 'zh') {
$lang = 'zh-cn';
} elseif ($lang == 'en') {
$lang = 'en-us';
}
}
}
// 设置语言
if (in_array($lang, config('lang.allow_lang_list'))) {
Lang::setLangSet($lang);
cookie('think_lang', $lang, 3600 * 24 * 365);
}
return $next($request);
}
}
在app/middleware.php中注册中间件:
return [
// 全局中间件
appmiddlewareDetectLanguage::class,
// 其他中间件...
];
2. 命令行语言包生成工具
创建自定义命令生成语言包:
// 在app/command/LangGenerate.php
<?php
namespace appcommand;
use thinkconsoleCommand;
use thinkconsoleInput;
use thinkconsoleOutput;
class LangGenerate extends Command
{
protected function configure()
{
$this->setName('lang:generate')
->setDescription('Generate language files from database');
}
protected function execute(Input $input, Output $output)
{
// 这里实现从数据库读取多语言内容并生成语言包文件
$output->writeln('Language files generated successfully!');
}
}
七、最佳实践与常见问题
1. 性能优化建议
- 使用OPcache加速PHP执行
- 对语言包文件进行缓存
- 避免在循环中使用lang()函数
- 对频繁访问的多语言内容使用Redis缓存
2. 常见问题解决
Q: 语言切换不生效?
A: 检查中间件是否正常注册,cookie是否设置成功,语言是否在allow_lang_list中
Q: 模板中语言变量不显示?
A: 确保语言包文件路径正确,键名匹配,文件编码为UTF-8无BOM
Q: 如何扩展更多语言?
A: 在allow_lang_list中添加语言标识,创建对应的语言目录和文件即可
八、总结
本教程详细介绍了ThinkPHP 6.x中实现多语言网站的完整方案,包括:
- 基础配置与语言包创建
- 控制器与模板中的多语言处理
- 数据库内容的多语言存储方案
- 自动语言检测中间件实现
- 性能优化与常见问题解决
通过这套方案,你可以轻松构建支持多语言的国际化网站,满足不同地区用户的访问需求。
完整项目代码已上传GitHub:https://github.com/example/tp6-multilang