网站如何实现多语言架构,比如同时支持中,英,法,俄

2025年05月05日 04:31
有3个网友回答
网友(1):

此文转载至:黄熊

电子商务网站多语言版设计思路

1. 数据库设计

1. 分库,还是分表

2. 单表还是多表1234

这步其实很关键:首先 这直接涉及到代码逻辑,一有不慎,可能会导致原有方案失效

说说我们的设计思路吧!

我们采用的是分库方式!

一种语言一个数据库

这样的好处有哪些呢?

1.避免单库数据量过大,导致查询难以优化。

举个例子:假设有2种语言,中文和英文。在商品表中,一个商品在不同语言下,其实还是同一件商品,他们有共同的属性,共同的价格,共同的库存等等;如果放在一个库中那么本来商品数据有100W,现在直接变成了200W。so优化起来是不是更麻烦了呢。而且对于像商品这种表,更新操作是非常频繁的,这样就要不断的去维护索引,这其中开销也是蛮大的。12

- 为什么不用分表? 
假如一种语言一个表,那跟分库道理不就一样了吗? 
其实我个人觉得分表有很多不足的地方。

  • 如果采用一个语言一张表,那么我们表的数据过大怎么办呢?这时候是不是还要继续分表呢?就目前的状况来看,很多公司都会采用分表去解决。也就是说要分2次表,这样不是很麻烦吗,而且表在同一个数据库中,数据量变大的时候怎么办呢,当达到Mysql储存上限(这里指的是mysql存储到一定数据时候就变得难以优化的情况)不就更麻烦吗? 
    所以我们采用了分库策略。

  • 表如何设计

    需要中英文对于的表,放到对于的库中即可,无需把所有的表都copy

    举个例子 
    商品表:

  •  id  title  stock status1

  • 假设我们的商品字段如上 
    这个时候我们添加商品的时候肯定是要往数据库(多个语言)里面添加数据。也就是说我添加了一个中文语言的商品,对应的英文数据库也应该插入同样的数据。然后再去编辑英文的商品数据。这样就保证了一个商品是一定会有多语言的。 
    那么我们如何做到同时添加 
    1. 刚开始想用触发器直接同步添加,可是这样一个库就要建立一个触发器?很显然,这样肯定就会陷入一个死循环中。(事实上MySQL是会报错的,为什么我就不说了)。所以这种偷懒的方案是不能实现得了啊。 
    2. 后来我想用存储过程去实现,但是呢,存错过程确实存在不少问题,可以参考我的一片文章 MySQL 存储过程的优缺点 。so只能放弃这种方案 
    3. 修改PHP框架的数据库操作方法。 
    我们采用的是THINKPHP。 这里说下如何修改tp 的 add . 
    tp的add方法是声明在Model下。所以我们新建一个commonModel来继承他的Model类

    首先要在配置文件中配置好多个数据库dsn

  • eg : 'DB_LIST' => array('DN_CN' => 'mysql:XXXX',                          'DN_EN' => 'mysql:XXXX'

  •                          );1234

  • 配置公共数据库的表

  • eg 'LANG_TABLE' => array(    'goods' => array('stock,status'), //这里配置的是该表需要更新的字段;比如商品的库存和状态肯定都是一致的)123

  • 以下是伪代码protected $dbName;  //数据库名protected $tableName; //表名protected $data;  // ORM创建的数据对象protecteds $option;  //查询条件等function __construct(){}function add($data,$option,$replace){

  •    if(!$data)    $data = $this->data;//如果是create的话,那么add一次之后,$this->data 会被清空


  •    parent::add($data,$option,$replace); //往当前库插入数据

  •    //切换数据库

  •    $this->dbName = 'XXXX';  //这里我们的库都在同一台服务器上,所以不用重新连接

  •    //如果在不用数据库,那么就读取DB_LIST配置来重新连接数据库。$this->db($id,$dsn);这样切换了数据库

  •    parent::add($data,$option,$replace);


  •    //切换回当前数据库

  •    $this->dbName = 'xxx';

  • }12345678910111213141516171819202122

  • 删除也是同理

    更新数据

    一个表中肯定会有一些字段是不用做多语言的,但是必须保证不用语言下的数据是一致的。比如商品价格,商品库存等 
    这个时候更新了一条记录,也要去同步下其他库的数据

  • 正如上面配置。 我们只需要把需要同步的字段配置好就行了function save($data,$option){

  •    parent::save($data,$option);    //切换数据库

  •    //对比$data 的key也配置的字段,取交集 $field

  •    parent::save($field,$option);  //如果是create的数据,记得对data进行赋值}

  • 其他tp的操作方法(如execute  addAll)我就不演示了。12345678910

  • 其实上面是很简单的。真正的重点在下面

    我们取商品的数据的时候通常是通过id去查询。

    那么我们多个库的时候,要取数据还能用id吗?

    如果能用id那么这篇文章已经结束了,哈哈!

    那么为什么不能用id了呢?

    其实很简单的道理:你没办法保证多个语言库的id是一致的,因为我们id是increament,so id没办法同步?举个例子:A用户往中文库插入一条数据,id 为100,这时候b用户往英文表插入一条数据id也有100,(这种情况是很有可能发生的,所以id肯定会不一样)?

    换个角度想想:如果我们加事务呢,这样是不是能保证数据一致性呢?其实这更可怕,很可能会造成死锁!

    Why ? 死锁其实道理很简单。

    A用户往中文库插入一条数据,id 为100,这时候中文库的表肯定被锁住了,这时候b用户往英文表插入一条数据id也有100,这时候英文库的表也被锁住了。但是他们又要同步到其他库。这时候A这边会发现英文库的表锁了,那么它要插入数据就必须等英文库的表解锁。但是与此同时b用户也会发现中文库的表锁了,它也要等解锁。这样就造成了双方都在等。死锁就这样形成了。 
    所以id是很不靠谱的。

    解决方案: 
    新增一个字段,类型为int,该字段的生成规则可是时间戳+随机数(这里面还涉及到一些算法,我就不公布了)。(为什么是int我就不解释了,很简单的道理)。这样多个语言的数据就通过此字段来获取(因为这个值是事先生成的,每个库的值都是一样的,所以不会冲突)。

网友(2):

无非就是分表或者分字段

网友(3):

做多语言就可以呀