2020-07-28

国际化技术方案

作者 货拉拉技术

当前版本 v2.8.12

一、一套代码–目标

 当前系统支持国际化后,后续产品功能设计和技术开发都在同一个系统内完成,   使用同一个系统的代码和产品部署到其它地区和国家,实现功能复用避免重复造轮子,前期不考虑通过多套代码方式实现定制化需求

二、一套代码–产品方案

系统开发的部分功能根据需求带开关设置,不同国家和地区根据城市需求在后台系统配置对应功能开关,如果个别地区需要定制化,系统前期可能通过新增定制模块解决

三、一套代码–git开发步骤

3.1 主要步骤

序号步骤说明
1.从master分支fork出国际化feature分支进行开发feature分支代码基础架构考虑支持模块化开关配置
2.国内常规迭代上线后, 定期合并到国际化feature分支减少后续国际化feature分支合并到master分支的冲突
3.国际化feature分支开发&测试完成,合并到master分支实现一套代码

3.2 步骤2拆解

序号步骤说明
2.1.备份国际化feature分支 
2.2.国际化ffeature分支所有国际化功能先合成一个点 
2.3.国际化feature分支对着master分支rebase不会影响master分支
2.4.解决冲突后,删除远端的国际化feature分支,强推本地feature分支到远端国际化功能改动始终只有1个点,同时这个点始终是最新commit点

四、一套代码–consul配置中心

当前只考虑php应用,java还是使用阿波罗配置中心

4.1 第1次主要步骤

序号步骤说明
1.写死在代码里的配置抽到配置文件 
2.将配置文件的路径及配置文件通过邮件发给运维配置文件作为附件,配置路径写到正文
3.运维根据邮件内容将相关配置录入配置中心 
4.运维根据SOP配置相关项目 

4.2 后续配置调整主要步骤

序号步骤说明
1.将配置文件的路径及配置内容通过邮件发给运维配置内容和配置路径写到正文
2.运维根据邮件内容将相关配置录入配置中心 

五、多个国家共享同一个集群(后面要支持)

数据划分最小粒度”城市”

编号事项说明方案
1.使用相同的域名 根据请求参数区别不同国家和城市的请求
2.使用相同的web进程同一个进程服务不同国家的请求根据请求参数区别不同国家和城市的请求
3.使用相同的数据库和表不同国家的数据放在同一张表通过字段标识不同国家和城市的数据
4.使用相同的缓存使用相同的缓存实例通过key区别不同国家和城市

六、请求协议公共参数调整

6.1 增加请求公共参数 (get请求方式)

app前端/web前端调用后端系统以及后端系统之间的调用都必须加上下面3个参数

参数类型组成结构举例说明
hlangstring(必传)语言标识语言+’_’+地区标识,都是小写例如 zhcn,enus,zhhk<br>https://docs.oracle.com/cd/E1321401/wli/docs92/xref/xqisocodes.html由用户选择语言
htzonestring(必传)时区标识国家+’_’+地区 ,都是小写例如 africaabidjan,indianantananarivo,indian_comoro由客户端逻辑决定当前使用的时区
hcountrystring(必传)国家标识数字,5位中国 1000, 印度 10000 

6.2 错误提示

原来后端返回的”msg”key作为国际化错误提示语

参数类型说明
msgstring错误提示国际化提示语默认为空串,当ret为非0返回非空串且值为国际化错误提示语

6.3 定时任务等非交互环境下公共参数获取方案

6.3.1 hlang参数
  • 第3阶段不传, 使用被调用系统的默认语言参数即可
  • 如果必须使用,通过司机和用户个人信息接口获取最近登录使用的语言
  • 获取hlang请封装一层函数或方法,方便后续改动获取逻辑
6.3.2 htzone参数
  • 第3阶段不传, 使用被调用系统的默认语言参数即可
  • 如果必须使用,使用集群默认国家对应的时区
  • 获取htzone请封装一层函数或方法,方便后续改动获取逻辑
6.3.3 hcountry参数
  • 需要传递,请封装一层函数或方法,方便后续改动获取逻辑
  • 当前孟买集群只有印度一个国家,封装层内部逻辑通过配置文件获取集群默认国家id即可
  • 后续如果要兼容一个集群多个国家的情况,需要从数据库层面解决,这个当前先不做

6.4 伪代码逻辑

6.4.1 获取集群默认国家id

# key名 hll_cluster_info
# 子key  default_country_id

6.4.2 获取国家的默认时区

# key名 hll_country_info_国家标识
# 子key default_timezone

七、 语言国际化-静态文案

7.1 语言国际化交互图

7.2 静态文案国际化逻辑

程序根据语言参数确定当前使用语言, 从语言配置文件或者数据库拉取对应翻译内容, 如果找不到,默认使用英文翻译

7.3 静态文案国际化步骤

顺序步骤负责人说明
1.插入自定义翻译函数开发把原来写死在代码里的文本替换成翻译函数+文本, 例如:”我是某某” => translate(“我是某某”)
2.生成源语言配置文件开发使用脚本或者工具根据翻译函数标签抽取生成配置文件,格式一般有key和value, key最好用英文,value必须为中文,支持多种标准格式
3.上传源语言配置文件到crowdin翻译平台开发通过”api/网页端/其它集成工具”上传, 翻译平台抽取value值作为源语言
4.翻译人员在翻译平台翻译翻译人员以中文为源语言翻译成其它目标语言
5.从crowdin下载翻译好的目标语言配置文件,同时集成到程序里开发通过”api/网页端/其它集成工具”下载,每种目标语言对应一个配置文件

7.4 各种程序使用的语言配置文件格式

程序语言配置文件格式说明
java.properties 
phpphp文件 
jsjson上传下载使用json,需要调整成js文件再集成到程序里
androidxml 
ios1. Strings <br>2. xliff同时使用2种

7.5 语言配置文件中key的组成规范

编号规范说明
1.必须是英文标识ios因其特殊性可以是中文
2.标识可按不同分类使用”_”拼接组成例如, driveriosinfo_mybalance 表示司机端ios个人信息页面我的余额

7.6 翻译平台crowdin介绍

网页

https://www.crowdin.com, 需要攀墙

功能

编号功能说明
1.支持绝大多数配置文件格式 
2.支持api/github/gitlab/网页端/crowdin客户端 上传下载配置文件 
3.平台提供专业机构翻译服务额外收费

八、 语言国际化-运营配置数据

8.1 运营配置数据-DB候选方案

编号方案说明举例
1.不同DB每种语言对应一个DB例如 dbzhcn, dbenin
2.不同表每种语言对应一个表例如 configcarzhcn,configcarenin
3.扩展表原来表拆分成一个主表和一个关联表, 主表存放跟多语言无关的列,关联表存放多语言差异的列例如 主表configcar 关联表configcarmaplang

8.2 运营配置数据-DB使用方案

使用方案3″扩展表”,但分2步走

步骤执行内容说明
1.1.1 前期绝大部分系统使用方案”不同DB”<br>1.2 前期少数系统使用方案”扩展表”1. 1 前期使用方案”不同DB”是为了开发效率,因为时间不够,不能一步到位<br>1.2 前期少数系统使用方案”扩展表”, 目的是让代码框架提前支持,提前发现风险点和解决问题,为过渡到步骤2做铺垫
2.所有系统逐步转到方案3(扩展表) 

8.3 运营配置数据后续优化

编号步骤说明
1.管理后台编辑数据存放都DB 
2.数据push到配置中心,下发到配置中心客户端 
3.业务通过配置文件读取运营配置数据 

九、 时区国际化

9.1 时区举例

下面图中 最上面为北京UTC+8,中间为UTC+0, 最下面为美国洛杉矶时区(带冬夏令时) 标题: fig:

9.2 系统分类

编号系统说明
1.app前端 
2.web前端 
3.接入层跟app或web前端直接交互的后端业务系统
4.服务层没有跟app或web前端直接交互的后端业务系统

9.3 时区接口协议方案–目标方案

新接口使用目标方案

编号事项说明
1.所有系统间交互协议关于时间的统一使用整形时间戳精确到毫秒
2.时间统一由app前端和web前端格式化 

9.4 时区接口协议方案–当前过渡方案

编号事项说明
1.所有系统新接口关于时间的统一使用整形时间戳时间戳精确到毫秒
2.所有系统关于时间查询的必须确保至少精确到分,因为数据库用的时区数据跟本地时区查询条件需要对齐例如,后端系统间协议参数如果为类似 2020-01-14, 需要改造成 2020-01-14 xx:xx ~ 2020-01-14 xx:xx
3.web前端到接入层的老接口关于时间的统一增加新key, 新key使用整形时间戳时间戳精确到毫秒
4.后端服务之间老接口关于时间的协议保持不变所有时间字符串参数一致为UTC+N N可以配置,目前统一为8
5.接入层负责把老接口中请求其它系统的时间字符串参数变成UTC+NN可以配置,目前统一为8
6.接入层负责把老接口中返回前端的时间字符串参数变成本地时间 

前端到接入层为老接口 标题: fig: 前端到接入层为新接口 标题: fig:

9.5 时区数据库设计方案–目标方案

  • 当前mysql datetime类型字段使用默认值current_timestamp大约有3000个
  • 默认值mysql current_timestamp不支持毫秒
  • mysql的datetime类型如果精确到秒以下,迁移到Mongodb和es可能有问题
编号事项说明
1.mysql时间类型全世界统一使用datetime, 值统一为UTC+8 
2.mysql datetime类型如果字段为业务使用,默认值不使用current_timestamp触发机制业务必须传字面值
3.mysql datetime类型如果字段为dba使用,默认值可以试用current_timestamp触发机制业务不需要传字面值
4.mongodb方案string类型值统一为UTC+8,date类型需要调整
5.es方案string类型值统一为UTC+8,date类型需要调整

9.6 时区数据库设计方案-当前过渡方案

编号事项说明
1.mysql数据库实例全世界统一配置为UTC+8时区这种情况下如果程序连接mysql没带时区参数会默认使用UTC+8时区
2.已有mysql字段保持不变目前有datetime和timestamp2种类型
3.新接口数据库设计关于时间的统一使用datetime类型 
4.程序确保全世界进库的datetime类型和timestamp的值都为UTC+8 

9.7 时区数据库设计方案-后续timestamp类型字段处理

timestamp字段目前大约有400个

编号事项说明
1.alter timestamp 成 datetime代码不需要改

9.8 时区改造–缓存改造注意事项

编号事项说明
1.缓存key涉及时间的必须使用本地时间例如key包含当天日期的要用本地时间
2.缓存过期时间以本地时间为参照例如当天过期指的是本地时间的当天过期

9.9 时区改造–定时任务环境注意事项

  • 同个集群多个国家的情况,因为不同国家的时区不一样,消费数据和启动时间都不一样
  • 同个集群多个国家的方案后续再做

9.10 代码修改逻辑

9.10.2 代码修改规范
编号事项说明
1.老接口新增加时间戳参数,命名规则为”老key_hts” 
2.服务层DB时区,服务层程序默认时区,服务层和接入层间接口参数时区全部统一UTC+NN可配置,目前为8
3.接入层和前端间接口参数时区为本地时区 
9.10.3 时间设置和转换逻辑

1. 定义全局时区常量
   根据配置文件找N的值,key名: hll_union_timezone, 目前N配置为8
   定义变量 HLL_UNION_TIMEZONE 为 N

2. 定义本地时区变量  HLL_LOCAL_TIMEZONE
  if 公共参数带时区 {
     定义HLL_LOCAL_TIMEZONE为 公共参数时区
  } else {
     根据配置文件找值,key名: hll_local_timezone, 代表集群默认本地时区
     定义HLL_LOCAL_TIMEZONE为集群默认本地时区
  }

3. 设置程序全局默认时区
   使用 HLL_UNION_TIMEZONE 设置程序全局默认时区
   php使用 date_default_timezone_set函数即可
 
## php 非默认时区转换可以使用以下日期对象来处理
## https://www.php.net/manual/zh/class.datetime.php
  
4. 封装函数把时间字符串参数转时间戳
   if 为本地时间字符串 {
      使用HLL_LOCAL_TIMEZONE转换
   } else {
      使用HLL_UNION_TIMEZONE转换
   }
  
5. 封装函数转换mysql的datetime值为UTC+N  
   时间戳作为函数参数,根据HLL_UNION_TIMEZONE直接转成datetime字符串

9.10.4 协议逻辑-接入层

1. 参数场景
以上面画的图为准


2. 读取前端参数逻辑
   if  客户端为新接口  {
       if “new_timestamp1″key有值 {
           使用 “new_timestamp1″key的值
       } else {
          if “new_timestamp1″key为必传参数
               报错
           }
       }
   }  else {   // 老接口
       if “time1_hts”key有值 {
           使用”time1_hts”key的值
      } else if “”time1″key有值 {
           使用”time1″key的值
      } else {
           if “time1_hts”key为必传参数
                报错
           }
      }
  
   }
  


2. 返回客户端数据逻辑
   if  客户端为新接口  {
       返回new_timestamp6  // 只返回时间戳数据 
   }  else {
      ##原来协议返回参数保持不变
      ##多返回时间戳配对key
       返回time6_hts // 多返回时间戳key
       ## 老的时间串time6必须转成本地时间, 因为前端可能不格式化直接展示,所以接入层兼容
       time6 = 根据本地时区通过time6_hts转换得到
       返回time6 // 原来协议返回参数key名不变
   } 
  

3. 请求服务层逻辑
   if  调用服务层接口为新接口  {
       只传时间戳请求参数
   }  else {
       ##原来协议请求参数保持不变
       ##如果协议包含时间字符串,确保为UTC+N,N的值目前为8
       ##如果协议包含时间字符串,且没有明确表示时间范围,这种情况一般是只有一个时间参数(例如当天日期),需要新增2个时间戳key解决
       例如如果传递请求参数time_old
       if time_old没有明确时间范围 { // time_old原来格式可能是 2020-01-14(印度本地时区)
          time_old_shts = “2020-01-14 02:30:00″的时间戳格式 // 注意time_old_shts是时间戳格式,精确到毫秒
          time_old_ehts = “2020-01-15 02:30:00″的时间戳格式  // 注意time_old_ehts是时间戳格式,精确到毫秒
          传递请求参数time_old_shts和传递请求参数time_old_ehts
       }
   } 

4. 调整数据库查询逻辑
  
   ## 对于没有明确表示时间范围,由于新增了时间戳key,需要调整对应db查询逻辑
   time_old原来格式可能是 2020-01-14(印度本地时区)
   time_old_shts = “2020-01-14 02:30:00″的时间戳格式 //新增的时间戳key 注意time_old_shts是时间戳格式,精确到毫秒
   time_old_ehts = “2020-01-15 02:30:00″的时间戳格式 // 新增的时间戳key,注意time_old_ehts是时间戳格式,精确到毫秒
   select * from table where date=”2020-01-14″ // 原来查询 sql 
   改成
  select * from table where date >=”2020-01-14 02:30:00″ and date < “020-01-15 02:30:00” // sql
  
 

9.10.5 协议逻辑-服务层


1. 参数场景
以上面画的图为准

2. 读取上游后端系统参数逻辑
   if  调用接口为服务层新接口  {
       if  “时间戳”key有值 {
           使用 “时间戳”key的值
       } else {
          if “时间戳”key为必传参数
               报错
           }
       }
   }  else {   // 老接口
       协议保持不变,读取的时间字符串的值一定位UTC+8
   }
  


2. 返回上游后端系统数据逻辑
   if  调用接口为服务层新接口  {
       只返回时间戳数据 
   }  else {
       ##原来协议返回参数保持不变
        ##如果返回参数中包含时间字符串,确保为UTC+N, N的值目前为8
   } 
  
  
     
3. 请求其它服务层逻辑
   if  调用服务层接口为新接口  {
       只传时间戳请求参数
   }  else {
       ##原来协议请求参数保持不变
       ##如果协议包含时间字符串,确保为UTC+N,N的值目前去8
       ##如果协议包含时间字符串,且没有明确表示时间范围,这种情况一般是只有一个时间参数(例如当天日期),需要新增2个时间戳key解决
       例如如果传递请求参数time_old
       if time_old没有明确时间范围 { // time_old原来格式可能是 2020-01-14(印度本地时区)
          time_old_shts = “2020-01-14 02:30:00″的时间戳格式 // 注意time_old_shts是时间戳格式,精确到毫秒
          time_old_ehts = “2020-01-15 02:30:00″的时间戳格式  // 注意time_old_ehts是时间戳格式,精确到毫秒
          传递请求参数time_old_shts和传递请求参数time_old_ehts
       }
   } 


4. 调整数据库查询逻辑
  
   ## 没有明确表示时间范围,由于新增了时间戳key,需要调整对应db查询逻辑
   time_old原来格式可能是 2020-01-14(印度本地时区)
   time_old_shts = “2020-01-14 02:30:00″的时间戳格式 //新增的时间戳key 注意time_old_shts是时间戳格式
   time_old_ehts = “2020-01-15 02:30:00″的时间戳格式 // 新增的时间戳key,注意time_old_ehts是时间戳格式
   select * from table where date=”2020-01-14″ // 原来查询 sql 
   改成
  select * from table where date >=”2020-01-14 02:30:00″ and date < “020-01-15 02:30:00” // sql

9.11 时区相关方案讨论过程笔记

1.DB用UTC+N方案,延迟决定老数据处理方式,用datetime
  不改老数据的原因是成本高
  UTC+N的原因是兼容老数据
  用datetime的原因是不用改数据库和兼容老数据,并且不同语言对timestamp的转换不同,有的用毫秒转,有的用秒转,还有些用微妙或纳秒。
问题:如果老数据有日期字段是datetime以外的类型是否需要处理(如timestamp、int、string等)?
目前分析由于timestamp和int本质上都是timestamp,timestamp都是UTC+0,天然支持国际化,不需要额外处理,后续遇到再关注

2.后端服务之间的通讯日期格式新增字段用timestamp,老字段新增一个相应的timestamp,老字段不变(遵循接口变更原则)
  其他方案:ISO8601,datetime
  由于不同时区已经在api接入层统一转成同一个时区,所以相关日期字段不需要携带时区信息,故不需要用ISO8601
  而datetime由于无法确认是否有转过时区,所以统一用timestamp,可以在不携带时区信息的前提下,保证表示时区是UTC+0

3.前端新API,日期参数用timestamp
   其他方案:ISO8601
   原因是ISO8601需要多做一层解析(部分语言)

4.前端请求参数,旧API保持datetime,APP或前端选城市时,返回当前城市的时区,API公共参数需要接收一个时区(timezone),但是不约束接收到的时区是否与当前城市的时区是否是一致的,这个由前端根据业务规则判断
  时区参数关于timezone或+n
  程序语言获取timezone比较方便
  传递timezone比较标准

十、 货币国际化

https://en.wikipedia.org/wiki/ISO_4217#Active_codes

10.1 货币国际化协议和数据库方案-目标方案

编号事项说明
1.格式化逻辑统一放在前端 
2.计算逻辑关于四舍五入的精确从配置读取 
3.后端提供新接口返回当前国家货币信息 
4.增加货币类型字段 
5.增加最小存储单位后面的小数字段 

精确到人民币分的情况,1元=100分

精确到人民币里的情况,1元=100分,1分=10厘

10.2 货币国际化协议和数据库方案-当前过渡方案

编号事项说明
1.格式化逻辑统一放在前端 
2.计算逻辑关于四舍五入的精确从配置读取 
3.后端提供新接口返回当前国家货币信息 
4.增加货币类型字段支付系统评估可选

精确到人民币分的情况,1元=100分

10.3 增加请求公共参数 (get方式)

业务调用支付系统多增加国家标识

参数类型组成结构举例说明
hcurrencystring(必传)货币类型国际货币编码,小写例如 cny表示人民币 

10.4 货币国际化任务梳理

编号事项说明
1.新的功能设计使用目标方案货币类型字段必须有,小数字段待评估
2.格式化逻辑统一放在前端第3阶段必须完成
3.部分后端系统计算逻辑关于四舍五入的精确从配置读取第3阶段必须完成
4.后端提供新接口返回当前国家货币信息第3阶段必须完成
5.增加货币类型字段支付系统评估可选,可以按阶段按模块做
6.增加最小存储单位后面的小数字段支付系统评估可选

10.5 代码逻辑

10.5.1 前端格式化逻辑


1. 接入层新增接口返回当前国家货币信息接口如下
  http://wiki.huolala.work/pages/viewpage.action?pageId=4850740
  
2. 前端根据货币信息接口配置进行格式化  

10.5.2 接入层和服务层逻辑


1. 读取支付配置信息
  
   # key名 hll_cluster_info_国家id
   # 子 key currency
   # 参照 16.5配置

2. 涉及计价逻辑调整
   现有计价写死了精确到角, 例如 449分会变成450分,精确的位数改成从配置文件读取

10.5.3 支付系统

1. 增加货币类型逻辑修改

十一、 地址国际化

11.1 地址国际化协议和数据库方案

编号事项说明
1.接口协议请求和返回新增地址标识参数参数后缀名称place_id
2.数据库保存每个地址标识id 
3.如果调用sdk失败,使用用户输入的内容 

11.2 地址国际化任务梳理

编号事项说明
1.app和web前端调用后端lbs服务逻辑调整第3阶段必须完成
2.app和web前端下单新增地址标识参数第3阶段必须完成
3.lbs服务接口调整第3阶段必须完成
4.用户接入层/司机接入层/core层请求和返回协议新增地址标识参数第3阶段必须完成
5.用户接入层/司机接入层调用lbs服务翻译地址第3阶段必须完成

11.2 代码逻辑

11.2.1 app和web前端

1. 用户定位调用 lbs 的 google poi检索接口,拿到 place_id
2. 使用 place_id 调用 lbs 的 google poi详情接口拿到经纬度
3. 下单接口增加相关place_id参数

11.2.2 lbs服务

1. 新增相关接口
   http://laladoc.huolala.cn/document/7061/detail

11.2.3 ucore/dcore

1. 协议请求和返回新增相关place_id参数
2. 相关place_id参数保存到DB

11.2.4 uapi

1. 协议上透传相关place_id参数给ucore

11.2.5 抢单大厅和dapi

1. 返回客户端相关地址如果翻译,调用lbs相关服务
2. 使用 place_id 调用 lbs 的 google poi详情接口
   2.1 需要判断现有地址跟翻译后地址的经纬度的曲面距离是否在100米内
   2.2 如果没在100米内降级使用geocode接口(精确度下降)
   2.3 google poi详情接口返回错误,降级使用geocode接口

十二、 数据库实时内容翻译

如果有必要, 部分用户提交数据可以通过翻译引擎实时翻译

十三、 语言国际化-场景推送

根据用户或司机最近1次选择的语言进行推送

13.1 方案逻辑

编号步骤说明
1.用户登录或司机登录后端记录所使用语言需要core服务记录到数据库
2.用户或司机切换语言后端记录所使用语言需要core服务记录到数据库
3.程序优先从通信参数获取语言参,找不到再调用接口获取最近1次司机或用户所使用的语言 

13.2 方案数据库设计

用户表和司机表新增语言字段 language

13.3 接口改动

  • 新增更换语言接口
  • 登录逻辑新增语言进库逻辑
  • 返回司机和用户信息新增语言返回参数

十三、 语言国际化-接口数据支持多语言

目前看来调用ops2的部分接口,例如citylist, 原来只返回中文的文案,如果支持多语言, 返回的数据要同时包含1个国家范围下的所有语言文案,所以协议要改动,同时调用方的缓存key和内容也要改动

十五、域名修改

15.1 内部域名调整规则

  • 根据不同集群,域名第3部分调整成集群物理位置的缩写
  • 例如 ucore.myhll.cn 调整成 ucore.myhll.sg, sg代表新加坡集群

15.2 外部域名调整规则

  • 域名加上前缀,前缀标识为集群物理位置的缩写
  • 域名中间部分变成 lalamove
  • 域名后缀如果是work则保持不变,如果不是work则改成com
  • 例如在印度, dapi.huolala.cn改成in-dapi.lalamove.com, lbs.huolala.work改成in-lbs.lalamove.work

15.3 集群缩写

编号集群缩写
1.大陆cn
2.香港hk
3.新加坡sg
4.孟买in

15.4 新加坡stg新的域名规则-以这个为准

域名分类大陆stg域名对应新加坡stg域名说明
外网cn域名xx-stg.huolala.cnsg-xx-stg.lalamove.com 
外网work域名xx-stg.huolala.worksg-xx-stg.lalamove.work 
内网域名xx-stg.myhll.cnxx-stg.myhll.sg 

15.5 新加坡stg以前域名规则-废弃

域名分类大陆stg域名对应新加坡stg域名说明
外网cn域名xx-stg.huolala.cnxx-stg.huolalamove.net 
外网work域名xx-stg.huolala.workxx-sg-stg.huolalamove.work 
内网域名xx-stg.myhll.cnxx-stg.myhll.cn域名没有变化

十六、后端配置修改方案

配置包含 数据库配置、缓存配置、域名配置等

16.1 php修改方案

编号步骤负责方说明
1.提供需要修改的域名列表和负责人应用运维提供在线可以编辑的文档,文档包含域名和负责人,对应git地址/git分支/配置文件列表留空,需要开发后续填充
2.git上修改配置文件开发从现有大陆分支fork出新分支,新分支修改配置文件
3.在线文档填充git地址/git分支/修改配置文件列表开发开发人员开发完成后,在线文档对应域名填充git相关信息
4.使用脚本分析在线文档,自动拉取git地址对应文件应用运维自动化拉取对应php配置文件内容
5.分析php配置文件内容,调用consul配置中心api插入数据到consul应用运维 

16.2 java修改方案

编号步骤负责方说明
1.应用运维把大陆的阿波罗配置同步到孟买阿波罗配置中心应用运维key和value都是大陆的
2.提供需要修改的域名列表和负责人应用运维提供在线可以编辑的文档,文档包含域名和负责人,对应”进度”列留空,需要开发后续填充
3.开发在阿波罗平台修改配置开发每天更新对应域名的修改进度

16.3 国家标识id列表

参考ops2配置 http://wiki.huolala.work/pages/viewpage.action?pageId=6728137

国家id
中国1000
印度10000

16.4 国际化新增配置梳理

key名php使用下划线,java使用.号

编号key说明孟买集群的值
1.hllclusterinfo获取集群配置信息 
2.hllcountryinfo_国家id获取国家配置信息 

16.5 孟买具体配置信息

1. 集群配置信息
    # key名 hll_cluster_info  
   
    # php key名 hll_cluster_info => array
       “default_country_id” => 10000, // 该集群的默认国家id
       “country_list” => array(  // 该集群的国家列表
            10000
        )
    )
   
    # java key名 hll.cluster.info,  模块名 core.localization.config
    {
       “default_country_id” : 10000, // 该集群的默认国家id
       “country_list” : [ 10000 ]  // 该集群的国家列表
    }

2. 国家配置信息
     # key名 hll_country_info_10000

   # php key名 hll_country_info_10000 => array (
       ‘default_timezone’ => ‘Asia/Kolkata’,  // 该国家的默认时区
      ‘default_lan’ => ‘en_in’,  // 该国家的默认语言,印度英语
       ‘lan_list’ => array(  // 该国家的语言种类
          0 => ‘en_in’,  // 印度英语
          1 => ‘hi_in’, //
          2 => ‘ta_in’, // 
          3 => ‘gu_in’, //
       ),
       ‘currency’ => array(  // 该国家的货币信息
           “code”: “inr”,
        “name”: “卢比”,
        “symbol”: “₨”,
        “standard_unit”: “inr”
        “min_unit”: “paise”
        “rate”: 100,
        “seg_len”: 3,
        “seg_mark”: “,”,
        “decimal_mark”: “.”,
        “precision_len”: 1
        “price_rate”: 10
       )
   )

 
   # java key名 hll.country.info.10000  ,  模块名 core.localization.config
   # java格式如下,为json字符串   
   {
      “default_timezone” : “Asia/Kolkata”,  // 该国家的默认时区
      “default_lan” : “en_in”,    // 该国家的默认语言,印度英语
       “lan_list” : [ “en_in”,”hi_in” ], // 该国家的语言种类
       “currency” : {     // 该国家的货币信息
         “code”: “inr”,
        “name”: “卢比”,
        “symbol”: “₨”,
        “standard_unit”: “inr”,
        “min_unit”: “paise”,
        “rate”: 100,
        “seg_len”: 3,
        “seg_mark”: “,”,
        “decimal_mark”: “.”,
        “precision_len”: 1,
        “price_rate”: 10
       }
   }

16.6 读取和传递公共参数–后端和web前端


1 读取hcountry

if (有传递hcountry参数) {
    if( hcountry参数 没有在 该集群国家列表中 ){
        阻塞性报错
    } else {
       $hcountry = 传递的hcountry参数
    }  
} else {
    阻塞性报错 //


2. 传递hcountry
    使用步骤1的 $hcountry值传递


3. 读取hlang

if (有传递hlang参数) {
    if( hlang参数 没有在 该集群国家语言种类中 ){
        $hlang = 该国家的默认语言
    } else {
       $hlang = 传递的hlang参数
    }  
} else {
    $hlang = 该国家的默认语言


4. 传递hlang
    使用步骤3的 $hlang值 传递


5. 读取htzone
if (有传递htzone参数)
    $htzone = 传递的htzone参数
} else {
    $htzone = 该国家的默认时区


6. 传递htzone
    使用步骤5的 $htzone值传递

16.7 读取和传递公共参数 –app前端


1 读取hcountry
   $hcountry =  用户选择的国家

2. 传递hcountry
    使用步骤1的 $hcountry值传递


3. 读取hlang

    $hlang =  读取系统语言参数转换得到  // 假设拿到为 en_in

4. 传递hlang
    使用步骤3的 $hlang值 传递


5. 读取htzone
    $htzone =  读取系统时区参数转换得到

6. 传递htzone
    使用步骤5的 $htzone值传递

16.8 多语言逻辑-非ops2配置接口

假设以下条件
# 调用方传递参数值为 $hlang
# 默认语言为 $hlang_def
# 语言种类列表为 $hlang_list


1. 被调用方逻辑

$hlang_search = $hlang  // 要搜索的语言

if ($hlang 不在 “$hlang_list”){
    $hlang_search = $hlang_def
}

if (本地有语言$hlang_search翻译文件){
   使用$hlang_search翻译文件
} else {
     if ( $search_lang != $hlang_def){
      使用$hlang_def翻译文件
     }
}


2. 调用方逻辑
if (返回数据有多种语言结构) {  // 例如  {“en_in”:”数据“,”hi_in”:”数据“}
    if (根据$hlang找到数据){
        使用$hlang对应的数据
    } else {
        if (根据$hlang_def找到数据){
           使用$hlang_def对应的数据
        }
    }
}

16.9 多语言逻辑-ops2配置接口

多语言相关接口列表 https://wiki.huolala.work/pages/viewpage.action?pageId=6730902


假设以下条件
# 调用方传递参数值为 $hlang
# 默认语言为 $hlang_def
# 语言种类列表为 $hlang_list
# $return_ext 表示调用ops2多语言接口参数,如果该参数存在并且不为0或false 返回该国家所有语言

1. ops2侧逻辑

$hlang_search = $hlang  // 要搜索的语言

if (存在$return_ext参数并且为ture或不等于0){
       返货该国家所有语言数据
}

if ($hlang 不在 “$hlang_list”){
    返回空数据
}

if (db找到$hlang_search内容){
   返回找到的内容
} else {
     返回空数据
}


2. 业务侧逻辑
# 如果请求ops2多语言接口返回数据有跟语言没关系的开关,同时有使用缓存,那么必须把所有语言的数据放在同一个缓存key里

if (需要多个语言数据){
    请求ops2带上 return_ext参数 且值为 1
}  else {
    不带 return_ext
}

十七、 后续考虑问题

1. 跟产品、大数据对齐时区时令数据划分问题
     针对同一个国家多个时区,同个城市有冬令时和夏令时,同一个订单起点和终点跨时区、跨令时,需要跟产品和大数据对齐输出报表时的数据划分问题,计费策略也要考虑这些因素   

2.用户名支持表情
    国外的用户名包含表情,数据库字段请使用utf8_mb4


3. 当前产品线通过一个字段标识,比如 小B,企业,但是无法区别不同国家不同城市的产品线,
    新增一个字段,该字段能够定位不同国家不同城市的产品线