国际化技术方案
当前版本 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个参数
参数 | 类型 | 值 | 组成结构 | 举例 | 说明 |
hlang | string(必传) | 语言标识 | 语言+’_’+地区标识,都是小写 | 例如 zhcn,enus,zhhk<br>https://docs.oracle.com/cd/E1321401/wli/docs92/xref/xqisocodes.html | 由用户选择语言 |
htzone | string(必传) | 时区标识 | 国家+’_’+地区 ,都是小写 | 例如 africaabidjan,indianantananarivo,indian_comoro | 由客户端逻辑决定当前使用的时区 |
hcountry | string(必传) | 国家标识 | 数字,5位 | 中国 1000, 印度 10000 |
6.2 错误提示
原来后端返回的”msg”key作为国际化错误提示语
参数 | 类型 | 值 | 说明 |
msg | string | 错误提示国际化提示语 | 默认为空串,当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 | |
php | php文件 | |
js | json | 上传下载使用json,需要调整成js文件再集成到程序里 |
android | xml | |
ios | 1. 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, 最下面为美国洛杉矶时区(带冬夏令时)
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+N | N可以配置,目前统一为8 |
6. | 接入层负责把老接口中返回前端的时间字符串参数变成本地时间 |
前端到接入层为老接口 前端到接入层为新接口
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+N | N可配置,目前为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比较标准
十、 货币国际化
10.1 货币国际化协议和数据库方案-目标方案
编号 | 事项 | 说明 |
1. | 格式化逻辑统一放在前端 | |
2. | 计算逻辑关于四舍五入的精确从配置读取 | |
3. | 后端提供新接口返回当前国家货币信息 | |
4. | 增加货币类型字段 | |
5. | 增加最小存储单位后面的小数字段 |
精确到人民币分的情况,1元=100分

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

10.2 货币国际化协议和数据库方案-当前过渡方案
编号 | 事项 | 说明 |
1. | 格式化逻辑统一放在前端 | |
2. | 计算逻辑关于四舍五入的精确从配置读取 | |
3. | 后端提供新接口返回当前国家货币信息 | |
4. | 增加货币类型字段 | 支付系统评估可选 |
精确到人民币分的情况,1元=100分

10.3 增加请求公共参数 (get方式)
业务调用支付系统多增加国家标识
参数 | 类型 | 值 | 组成结构 | 举例 | 说明 |
hcurrency | string(必传) | 货币类型 | 国际货币编码,小写 | 例如 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.cn | sg-xx-stg.lalamove.com | |
外网work域名 | xx-stg.huolala.work | sg-xx-stg.lalamove.work | |
内网域名 | xx-stg.myhll.cn | xx-stg.myhll.sg |
15.5 新加坡stg以前域名规则-废弃
域名分类 | 大陆stg域名 | 对应新加坡stg域名 | 说明 |
外网cn域名 | xx-stg.huolala.cn | xx-stg.huolalamove.net | |
外网work域名 | xx-stg.huolala.work | xx-sg-stg.huolalamove.work | |
内网域名 | xx-stg.myhll.cn | xx-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,企业,但是无法区别不同国家不同城市的产品线,
新增一个字段,该字段能够定位不同国家不同城市的产品线