likes
comments
collection
share

回顾Dart - 过度设计的国际化

作者站长头像
站长
· 阅读数 34

起因

我们的App作为To B产品的附加值在供客户使用。在今年5月份时,我们有了来自日本和美国的客户,为了满足客户的使用场景,App要开始完善国际化多语言使用场景。

现有项目分析

  • 项目在最初立项时,没有考虑到多语言使用场景,在代码中没有预留key
  • UI中非接口加载的数据,都是硬编码在view层
  • 项目在搭建底层框架时,依赖了GetX框架,如果要做多语言切换,只要需要处理多语言部分即可。

错误的初步改造

步骤一

生成txt文件:在dart语法中,字符串可以是"xx",也可以是'xx',起初我们全部按照"xx"去扫描项目中的文件,通过人工对比,发现漏掉了'xx'部分的,我们在编写扫描脚本代码时要注意。

步骤二

通过Chatgpt 生成唯一key:通过步骤一,我们得到了一份txt文件,里面包含了项目中会用到的所有中文, 大概格式如下:

"今天",
"明天",
"你好",

此时该Chatgpt登场,通过投喂示例,让Chatgpt帮我们生成了下面一份文件

"today": "今天",
"tomorrow": "明天",
"hello": "你好",

其中today就是我们项目中要使用的key,得益于GetX的支持,在项目中只要使用"today".tr,便可根据项目中的配置,展示对应的语言。

步骤三

错误的过度设计:版本在最初迭代中,汉字部分有多处重合,我抱着便于管理字符串的心态,设计了enum的使用场景,代码如下面:

enum XXKey {
    case today
    case tomorrow
    case hello
}

extension XXKeyExtension on XXKey {
    String get key {
        swith(this) {
            case XXKey.today:
                return "today";
            case XXKey.tomorrow:
                return "tomorrow";
             case XXKey.hello:
                return "hello"
        }
    }
}

class XXKeyConst {
    static get keys = {
        "en_US": {
           XXKey.today.key: "today", 
           XXKey.tomorrow.key: "tomorrow", 
           XXKey.hello.key: "hello", 
        },
        "zh_CN": {
           XXKey.today.key: "今天", 
           XXKey.tomorrow.key: "明天", 
           XXKey.hello.key: "你好
        }
    }
}

view中,"today".tr改成使用XXKey.today.key.tr

因为有Chatgpt的辅助生成,在业务中只要关心view中的替换逻辑即可。

错误处

可随着版本的迭代与维护,XXKey.today.key.tr这种使用方式变的异常繁琐。

首先要先整理新迭代中的所有文案,然后在使用Chatgpt生成如下内容:

/// 新的
case new

case XXKey.new:
    return "new";

XXKey.new.key: "new"

XXKey.new.key: "新的" 

每个词组都会生成上面四个内容,随着数量的增加,即使是复制粘贴,这份工作也变的越来越难维护。

在使用中,我发现定义的枚举extension中的key,并不是必须的。我这么做的初衷是为了方便管理,可随着数量的增加,枚举的方式使代码管理变的越来越复杂化。

回归正确的改造

化繁为简,参照正规做法:当我们拿到下面这份内容时,无非是想要它有中文的对应关系和英文的对应关系即可。

"今天",
"明天",
"你好",

通过Chatgpt,生成了下面内容

/// zh_CN.json
{
    "today": "今天",
    "tomorrow": "明天",
    "hello": "你好",
}

/// en_US.json
{
    "today": "today",
    "tomorrow": "tomorrow",
    "hello": "hello",
}

对比XXKey.today.key.tr这种用法,在项目中直接使用"today".tr显然更符合直觉逻辑,参与当前版本迭代的同事们,只需要去关心zh_CN.json中的key就行,枚举维护的这层工作被省掉,大家在代码合并上也减少了不必要的冲突。

但经过几次迭代,项目中已经存在了大量XXKey.today.key.tr这种写法,现在重新去修改,显然不符合我们的预期,这也让我之前的努力付之东流,大受打击。

尝试自动化

通过Python脚本去生成对应dart文件:分析XXKey.today.key.tr,在不采用枚举的情况下,可以是下面这种情况:

class XXKey {
    static const String today = "today";
    static const String tomorrow = "tomorrow";
    static const String hello = "hello";
}

关于.key的部分,我们也可以通过对String进行extension来处理

extension XXKeyString on String {
    String get key => this;
}

在项目启动的时机中,将zh_CN.jsonen_US.json加载到GetX所需要的多语言配置中,现有的XXKey.today.key.tr还是可以正常工作。

但关于class XXKey,如果还采取手动管理,这和最初的enum方案大同小异,经过我们对比,zh_CN.json文件在开发阶段就是比较完整的,en_US.json中的部分字段,还需要产品或者其他同事翻译后才可以正常使用。

我们通过类似于下面的Python脚本,将class XXKey自动生成

path = "../../zh_CN.json"  
with open(path, mode="r", encoding="utf-8") as file:  
    result = file.read()  
print(result)  
  
# str -> json  
result = json.loads(result)  
print(result)  
  
# 生成一个dart文件  
action = ["class Action {"]  
  
# 便利字典result  
for key, value in result.items():  
    action.append(f" static const String {key} = "{value}";")  
action.append("}")  
print(action)  
  
with open("action.dart", mode="w", encoding="utf-8") as f:  
    f.write("\n".join(action))  
  
print("生成成功")

当有新的文案需要添加,我们可以通过Chatgpt生成下面的内容即可

"today": "今天",
"tomorrow": "明天",
"hello": "你好"

在文案生成后,直接拷贝到zh_CN.json中,通过Python脚本,class XXKey也会生成最新的代码。

将上述内容发给产品,他们也可以很方便的进行翻译工作,等待翻译工作结束,我们直接放入到en_US.json中,因为class XXKey是根据zh_CN.json生成,view中的使用并不会受到影响,开发速度与体验大幅提升。

后续使用

因为历史版本的缘故,XXKey.today.key.tr这种使用方式我们会兼顾保留,在后续的迭代中,我们会统一使用XXKey.today.trview中预埋key

最后

经过此次改造过程,我也意识到,在进行一项长期工作时,一定要先三思而会后行,多参考一些优秀的设计。

代码最初的设计就是化繁为简,不要去过度设计,让本来简易的程序流程复杂化。

转载自:https://juejin.cn/post/7385003658390192163
评论
请登录