首页 > 其他分享 >《基于Modern工具包的本地化方式》的错误修正

《基于Modern工具包的本地化方式》的错误修正

时间:2023-04-04 20:02:15浏览次数:38  
标签:me service 本地化 Modern 工具包 Ext resourceName LocalizedService localized


在《基于Modern工具包的本地化方式》一文中实现的本地化方式忽略了在切换语言后,原始的文本值已经改变,要想再切换回去,由于找不到对应的本地化值,最终切换不了,因而,必须在第一次切换的时候记录下原始文本值,这样才能保证每次切换的时候都能找到对应值。

在前文中还有一个bug是当本地化先于组件完成初始化时,就不会监听localizedready事件。
本文还添加了语言切换按钮,用于切换语言。
以下是修正后的代码:
Localized.js

Ext.define('CommonShared.service.Localized', {
    alternateClassName: 'LocalizedService',
    singleton: true,

    config:{
        currentLanguage: null
    },

    requires:[
        'CommonShared.util.Url',
        'CommonShared.service.OAuth',
    ],
  
    isReady: false,

    constructor(config){
        const me = this;
        me.initConfig(config)
        me.initLanguages();
        me.loadResources();
    },

    initLanguages(){
        const me = this;
        let current = StorageService.get('lang');
        if(current) return;
        current = AppConfig.lang === 'zh-CN' ? 'zh-Hans' 
            : AppConfig.lang === 'zh-TW' ? 'zh-Hant' : AppConfig.lang;
        me.setCurrentLanguage(current);
        StorageService.set('lang', current);
    },

    loadResources(){
        const me= this;
        me.isReady = false;
        Ext.Ajax.request({
            url: URI.get('Configuration', 'localization'),
            headers: AuthService.getAuthorizationHeader(),
            scope: me
        }).then(me.loadSuccess, me.loadFailure, null, me);
    },

    loadSuccess(response){
        const me = this,
            obj = Ext.decode(response.responseText,true);        
        if(obj){
            me.remoteRawValue = {};
            Object.assign(me.remoteRawValue, obj);
            me.doOverride();
        }
        me.isReady = true;
        Ext.fireEvent('localizedready', me);

    },

    loadFailure(response){
        let obj  = Ext.decode(response.responseText, true),
            error = 'Unknown Error!';
        if(obj && obj.error) error = obj.error;
        Ext.Msg.alert('Error', error);
    },

    get(key, resourceName){
        const me = this,
            defaultResourceName = me.remoteRawValue.defaultResourceName,
            values = me.remoteRawValue.values;
        return resourceName && values[resourceName] && values[resourceName][key] 
            || ( values['ExtResource'] && values['ExtResource'][key] )
            || ( values[defaultResourceName] && values[defaultResourceName][key] )
            || key;
    },

    getLanguages(){
        return this.remoteRawValue.languages;
    },

    getCurrentCulture(){
        return this.remoteRawValue.currentCulture;
    },

    switchLanguages(value){
        const me = this, 
            current = me.getCurrentLanguage();
        if(current === value) return;
        me.setCurrentLanguage(value);
        StorageService.set('lang', value);
        me.loadResources();
    },

    localized(cls, name,  resourceName){
        name = Ext.String.capitalize(name);
        const originLocalized = cls.getOriginLocalized(),
            get = cls[`get${name}`],
            set = cls[`set${name}`];
        let value = originLocalized[name];
        //有原始值的,使用原始值返回
        if(value){
            if(set){
                set.apply(cls, [LocalizedService.get(value,resourceName)]);
                return;
            }
            return LocalizedService.get(value,resourceName);
        }
        //没有原始值的处理
        if(!get || !set) {
            //没有set或get方法的,直接返回
            value = name;
            originLocalized[name] = value;
            return LocalizedService.get(value,resourceName);
        };
        value = get.apply(cls);
        originLocalized[name] = value;
        if(!value) return;
        set.apply(cls, [LocalizedService.get(value,resourceName)]);
    },


    privates:{
        remoteRawValue: {},

        doOverride(){
            const me = this,
                values = me.remoteRawValue.values.ExtResource,
                newMonthNames = [],
                newDayNames = [],
                am = values['AM'] || 'AM',
                pm = values['PM'] || 'PM';
            if(!Ext.Date.originMonthNames)Ext.Date.originMonthNames = [].concat(Ext.Date.monthNames);
            Ext.Date.originMonthNames.forEach(month=>{
                newMonthNames.push(values[month] || month);

            });
            Ext.Date.monthNames = newMonthNames;

            if(!Ext.Date.originDayNames)Ext.Date.originDayNames = [].concat(Ext.Date.dayNames);
            Ext.Date.originDayNames.forEach(day=>{
                newDayNames.push(values[day] || day);

            });
            Ext.Date.dayNames = newDayNames;

            //console.log(Ext.Date)
            Ext.Date.formatCodes.a = `(this.getHours() < 12 ? '${am}' : '${pm}')`;
            Ext.Date.formatCodes.A = `(this.getHours() < 12 ? '${am}' : '${pm}')`;
    
            const parseCodes = {
                g: 1,
                c: "if (/(" + am + ")/i.test(results[{0}])) {\n" +
                    "if (!h || h == 12) { h = 0; }\n" +
                    "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
                s: `(${am}|${pm})`,
                calcAtEnd: true
            };
    
            Ext.Date.parseCodes.a = Ext.Date.parseCodes.A = parseCodes;
    
    
        },
    }


})

Component.js

Ext.define('CommonOverrides.shared.Component',{
    override: 'Ext.Component',

    config:{
        resourceName: null,
        localized: [],
        originLocalized: {}
    },

    initialize(){
        const me = this;
        me.callParent(arguments);
        if(LocalizedService && LocalizedService.isReady){
            me.onLocalized();
        }
        Ext.on('localizedready', me.onLocalized, me);
    },

    onLocalized(){
        const me = this,
            xtype = me.xtype,
            resourceName = me.getResourceName(),
            service = LocalizedService,
            localized = me.getLocalized();
        if(me.isButton || me.isMenuItem) {
            service.localized(me, 'text');
            return;
        }
        if(xtype === "loadmask"){
            service.localized(me, 'message');
            return;
        };
        if(me.isField){
            service.localized(me,'requiredMessage');
            service.localized(me,'validationMessage');
            service.localized(me,'label', resourceName);
            if(me.getPlaceholder) service.localized(me, 'placeholder', resourceName);
            if(me.getBoxLabel) service.localized(me ,'boxLabel', resourceName);
            if(xtype === 'datefield' || xtype === 'DatePicker'){
                service.localized(me,'minDateMessage');
                service.localized(me,'maxDateMessage');
            }
            if(xtype === 'numberfield'){
                me.decimalsText = service.localized(me, 'decimalsText');
                me.minValueText = service.localized(me, 'minValueText');
                me.maxValueText = service.localized(me, 'maxValueText');
                me.badFormatMessage = service.localized(me, 'badFormatMessage');
            }
            if(xtype === 'textfield'){
                me.badFormatMessage = service.localized(me, 'badFormatMessage');
            }
            me.setError(null);
            return;
        }
        if(me.isContainer){
            if(me.isPanelTitle || me.isPanel) {
                service.localized(me , 'title', resourceName);
                if(xtype === 'tooltip'){
                    service.localized(me , 'html', resourceName);
                }
                const collapsible = me.getCollapsible && me.getCollapsible();
                if(collapsible){
                    service.localized(collapsible, 'collapseToolText');
                    service.localized(collapsible, 'expandToolText');
                }
                me.doCustomLocalized(me, localized, resourceName);
                return;
            };
            if(me.isGridColumn){                
                service.localized(me ,'text', resourceName);
                return;
            }
            if(xtype === 'datepanel'){
                service.localized(me, 'nextText');
                service.localized(me, 'prevText');
                return;
            }
            if(me.isDataView){
                service.localized(me, 'loadingText');
                service.localized(me, 'emptyText');
                return;
            }
            // if(xtype === 'lockedgridregion'){
            //     service.localized(me, 'menuLabel');
            //     return;
            // }
        }
        me.doCustomLocalized(me, localized, resourceName);
    },

    doCustomLocalized(me, localized, resourceName){
        localized.forEach(key=>{
            LocalizedService.localized(me, key, resourceName)
        });
    }


})

Abstract.js

Ext.define('CommonOverrides.shared.plugin.Abstract',{
    override: 'Ext.plugin.Abstract',

    config:{
        originLocalized: {}
    },

    constructor: function(config) {
        const me = this;
        if (config) {
            me.cmp = config.cmp;
            me.pluginConfig = config;
            me.initConfig(config);
        }
        if(LocalizedService && LocalizedService.isReady){
            me.onLocalized();
        }
        Ext.on('localizedready', me.onLocalized, me);
    },

    onLocalized(){
        const me = this,
            type = me.type;
        if(type === 'gridrowdragdrop'){
            me.dragText =  LocalizedService.localized(me , 'dragText');
            return
        };
        if(type === 'listpaging'){
            LocalizedService.localized(me , 'loadMoreText');
            LocalizedService.localized(me , 'noMoreRecordsText');
        }
    },

});

Validator.js

Ext.define('CommonOverrides.shared.data.validator.Validator',{
    override: 'Ext.data.validator.Validator',

    config:{
        originLocalized: {}
    },

    constructor: function(config) {
        const me = this;
        if (typeof config === 'function') {
            me.fnOnly = true;
            me.validate = config;
        }
        else {
            me.initConfig(config);
        }
        if(LocalizedService && LocalizedService.isReady){
            me.onLocalized();
        }
        Ext.on('localizedready', me.onLocalized, me);
    },

    onLocalized(){
        const me = this,
            type = me.type,
             resourceName = 'ExtResource';
        if(type === 'bound' || type === 'length' || type === 'range'){
            if(type === 'bound') LocalizedService.localized(me ,'emptyMessage',resourceName);
            if(type === 'range') LocalizedService.localized(me ,'nanMessage',resourceName);
            LocalizedService.localized(me ,'minOnlyMessage', resourceName);
            LocalizedService.localized(me ,'maxOnlyMessage', resourceName);
            LocalizedService.localized(me ,'bothMessage', resourceName);
            return;
        }
        LocalizedService.localized(me ,'message', resourceName);
    },


})

语言切换按钮的代码:
Language.js

Ext.define('CommonShared.ux.button.Language',{
    extend: 'Ext.Button',
    xtype: 'languagebutton',

    ui: 'action',

    onLocalized(){
        const me = this,
            originLocalized = me.getOriginLocalized(),
            current = LocalizedService.getCurrentCulture(),
            displayName = current.cultureName.includes('zh') ? current.displayName: current.englishName;
        originLocalized['Text'] = displayName;
        me.setText(displayName);
        me.callParent();
        if(me.getMenu()) return;
        const menus = [];
        LocalizedService.getLanguages().forEach(l=>{
            menus.push({ 
                value: l.cultureName , 
                text: l.displayName, 
                handler: me.onSwitchLanguage,
            });
        });
        me.setMenu(menus);
        
    },


    onSwitchLanguage(sender){
        LocalizedService.switchLanguages(sender.value);
    }

    
})

采用这种本地化方式的一个麻烦是,要修改按钮的文本显示,必须修改原始值,不然显示的会是原始值,代码中的originLocalized['Text'] = displayName;就是用来修改原始值的,或者再想想有没有更好的办法。


标签:me,service,本地化,Modern,工具包,Ext,resourceName,LocalizedService,localized
From: https://blog.51cto.com/dqhuang/6169364

相关文章

  • 基于Modern工具包的本地化方式(上)
    新项目需要从服务器下载本地化资源,如果继续使用快速模板的本地化策略就很尴尬了,绝不可能等待本地化资源全部下载后再去加载项目,得另想办法。在研究过了《Internationalization&LocalizationwithSenchaExtJS》一文后,终于有思路了。文章的思路是通过重写Ext.Component来导入本......
  • 跨境出海东南亚,茄子科技(海外SHAREit Group)高效赋能企业本地化布局
    随着国内电商市场日趋饱和,意味着电商行业迈进残酷的存量竞争时代。为突破国内电商市场瓶颈,寻找一块尚待开垦的新增长市场才是跨境出海玩家破增长的最优解。东南亚国家是世界上发展最快的经济体之一,也是全球人口增长最快的地区之一,拥有人口规模、人口结构、经济总量、消费能力等得天......
  • OpenKE:知识图谱表示学习工具包
    OpenKE是THUNLP基于TensorFlow,PyTorch开发的用于将知识图谱嵌入到低维连续向量空间进行表示的开源框架。在OpenKE中,我们提供了快速且稳定的各类接口,也实现了诸多经典的知识表示学习模型。该框架易于扩展,基于框架设计新的知识表示模型也十分的方便。具体来说,OpenKE具有如下特点:1.......
  • LabVIEW Excel工具包快速读写EXCEL样式模板生成测试报告制作
    LabVIEWExcel工具包快速读写EXCEL样式模板生成测试报告制作YID:86199673187774245......
  • wine 运行Call of Duty Modern Warfare 2以及starcraft2方法
    必需条件:wine升级到1.3以上Linux已经正确安装显卡驱动其他需要东西:DirectX以及VC运行库这些东西请自己准备吧,不需要我一个一个说了然后关键是用wineregedit导入下面注册......
  • Modern.js v2 正式发布
    好消息,2023年3月16号字节跳动WebInfra团队宣布Modern.jsv2正式发布。字节跳动WebInfra团队从2021年10月27号发起Modern.js正式开源起,距离现在开发维护迭代已经50......
  • 快速上手Meta大语言模型LLaMA,构建“本地化ChatGPT”
    近期,Meta发布了人工智能大语言模型LLaMA,包含70亿、130亿、330亿和650亿这4种参数规模的模型。其中,最小的LLaMA7B也经过了超1万亿个tokens的训练。本文我们将以7B模型为例,分......
  • 修改node项目自动重启 | nodemon工具包
    1、为什么使用nodemon(1)在编写调试Node.js项目的时候,如果修改了项目的代码,则需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon工具包这个工......
  • JDBC笔记(三):基于JDBC的工具包
    本文主要介绍基于JDBC的两个优秀的工具包,ApacheDBUtils和SpringJDBC的基本应用。1、ApacheDBUtilsDBUtils样例的官网地址:https://commons.apache.org/proper/c......
  • IO流(二)之字符流、缓冲流、转换流、打印流,数据流,序列化流,File和IO工具包
    通过名字就很高区分,前面的单词代表着功能,后面的代表着类别一、字符流字节流:适合复制文件等,不适合读写文本文件字符流:适合读写文本文件内容具体的原因我们在前面的内......