Singleton之我见(四)

本文探讨了一个在使用Singleton框架进行国际化开发时遇到的问题,即部分UI内容在多线程环境中出现随机的英文显示。分析指出问题可能源于未正确使用Singleton的异步加载和路由守卫。解决方案是通过实现路由守卫确保翻译内容加载完成。开发者应当注意阅读文档并按照推荐方式进行编码,以避免类似问题。
摘要由CSDN通过智能技术生成

在之前的文章中,已不止一次的给大家介绍了开源国际化开发框架——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)其所推荐的方法论进行编码,则是避免“千里之堤毁于蚁穴”的不二法门。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值