Singleton之我见(四)

在之前的文章中,已不止一次的给大家介绍了开源国际化开发框架——Singleton。对于企业级大型应用,其优势的确是肉眼可见的。然后,这是否意味着只要引入了Singleton框架,国际化问题或者说国际化中的三层问题就彻底被解决了么?答案是否定的。在接下来的几篇短文中,我想给大家分享的内容就是即便在import Singleton后,因为种种不规范、不推荐的写法和配置下,直接引发了多种奇葩的国际化问题。

问题

首先,让我们一起来关注一个字符串读取问题,现象如下:

在产品的中文主页面上不断的点击导航栏,发现UI大部分内容都已经被本地化,但依然存在少量模块(例如Inventory模块)中的小部分UI 内容依旧保持英文。检查代码中的资源文件,确定该模块对应的string已经被本地化,不存在遗漏问题。回到中文导航栏继续点击,Inventory模块的内容莫名的又变成了中文,问题不再重现。然而与此同时会产生新的随机事件,原先已经显示中文内容的某些模块(例如Deploy模块)会发生同样的问题,UI中小部分内容发生了回退,变成了英文。这里需要注意的是,该问题出现的相当随机,没有必现的步骤可以遵循。

分析

遇到这个问题后,个人的第一反应是该问题是与多线程相关的国际化问题,我们在之前的文章《国际化与多线程》和《国际化与多线程—续》中总结过Python和C#中的异步方法带来的locale混乱问题,而眼下的问题则同之前总结过的有着极其高的相似度。然而事实究竟如何呢?本项目中已经引入了Singleton框架,而Singleton中Lazy Load Module中也确实提供了异步非阻塞load string的方案,官方文档中进行了清晰的说明,这里需要格外注意的是——我们务必要使用stream订阅,以确保在使用同步API时加载了数据。如果我们不想实现locale切换或订阅流事件,也可以通过相应路由守卫中的I18nDataGuard以阻塞的方式加载数据,然后直接使用同步API。

这里的路由守卫实现了访问特定路由组件前的翻译检查功能,检查通过则放行,否则就阻止访问。通过从路由参数中读取精简的Singleton配置,将i18nDataGuard配置为路由对象的一部分,为Lazy Module加载i18n资源,并在模块激活和初始化时做好准备。

// Sample code for I18nDataGuard

const routes: Routes = [
{
        path: '',
        component: SampleComponent,
        canActivate: [I18nDataGuard],
        data: {
        // 'vipConfig' is specified keyword of vip configuration.
        // In the simplified configuration of lazy loading module,
        // only the component name is required, and other fields are optional.
            vipConfig: {
                component: 'sample',
                sourceBundles: [ENGLISH]
            }
        }
    }
]

而本案的症结就在于开发人员既没有进行stream订阅,同时也未按照文档要求来实现i18n路由守卫。

解决方案

这里我们尝试选择第二种方式——路由守卫,来解决问题。首先在Lazy Load Module中,添加独立的了l10n.guard.ts文件。其次,在路由辞典中添加i18n路由守卫。

// Sample fixing code
// shared/guards/src/lib/ll10n/l10n.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { L10nService } from '@vmw/ngx-vip';

@Injectable()
export class L10nGuard implements CanActivate {
    constructor(private l10nService: L10nService) {}
    public canActivate(): Observable<boolean> {
        return this.l10nService.stream.pipe(map(() => true));
    }
}

//  subscriptions/src/lib/subscriptions-routing.module.ts
@Injectable()
export class SubscriptionGuard implements CanActivate {
    ….
    {
        path: 'list',
        component: Component1,
        canActivate: [L10nGuard],
    },
    {
        path: 'create',
        component: Component2,
        canActivate: [SubscriptionGuard, L10nGuard],
    },
…

再次刷新已经添加了canActivate[… L10nGuard]的模块,问题烟消云散,而未添加的模块老问题依然随机出现。

总结

归根结底,引入该问题的根源在于开发人员引入Lazy Load Module时,务必要用stream订阅来确保翻译内容加载完毕,或者在需要进行守护的模块中调用I18nDataGuard,这样不规范或者说不正确的使用直接引发了本案中的奇怪现象。其实,这种随意甚至有些想当然的情况在日常国际化研发过程中屡见不鲜,对于我辈一线编码人员来说,不断的阅读和准确的理解编程语言和Singleton这样开源框架对应的文档,严格的按照不同模式下(如Singleton中的Root和Lazy)其所推荐的方法论进行编码,则是避免“千里之堤毁于蚁穴”的不二法门。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值