查看: 126|回复: 0

前端系列——jquery.i18n.properties前端国际化解决方案“填坑日记”

[复制链接]

该用户从未签到

发表于 2019-11-3 21:18:51 | 显示全部楼层 |阅读模式
媒介:最近,新的平台还没有开发完成,原来的老项目又提出了新的需求:系统国际化。如果是前后端完全分离的开发模式,要做国际化,真的太简单了,有现成的办理方案,基于Node构建的时下热门的任何一种技能选型都有成熟的方案,比如:

  • vue + vue-i18n
  • angular + angular-translate
  • react + react-intl
但现在的情况是老的项目并没有使用这类架构。说起国际化,博主几年前就做过,在MVC内里实现国际化有通用的办理方案,主要就是通过资源文件的方式定义多语言。最初接到这个任务,并没有太多顾虑,毕竟这种东西有很成熟的办理方案,实现起来难点不会很大。可认真正动起来手来去实现的时候发现一些问题,这里先介绍下我们老平台的架构:MVC+WebApi,MVC项目负责页面渲染,webapi负责数据接口,是一种很传统的架构方式。国际化主要在MVC端去做就好了,可是由于MVC项目内里使用了大量第三方bootstrap组件,几乎95%的组件都是通过js去实现的,比如bootstrapTable,比如bootstrap-select,比如bootstrap-fileinput。如果按照传统的方式,仅仅在MVC内里去实现国际化,那么大量的js代码内里的中文没法统一处置惩罚,并且许多第三方组件有自己的本地化local文件,和后端的国际化很难统一处置惩罚;可能有人又说,那就前后端分开国际化呗,这种方案博主真的想过,但是想到要维护两套资源文件,果断放弃。最后照旧决定直接维护一套,做前端国际化好了。于是在网上搜索基于jquery的国际化,如出一辙,几乎都说的是jquery + jquery.i18n.properties这种方案,既然各人都这么选型,那博主也按照这种思路去做好了。
在实现的过程中,有许多值得注意和分享的东西,在此写一个填坑笔记,盼望对各人有帮助!接下来,博主就一步一步带领各人办理这个过程中遇到的一些坑,如果有这个需求的童鞋可以关注下,可能这些问题你也会遇到。
本文原创地点:http://www.cnblogs.com/landeanfen/p/7581609.html
一、jquery.i18n.properties通用办理方案

关于jquery.i18n.properties的使用,网上资料许多,比较完备的使用可以参考 这篇 ,有比较详细的使用阐明。这里博主简单概述下过程。
1、必要引用的js文件

先在你的项目文件内里添加如下目录布局

首先页面引用的js文件如下
  1.            
复制代码
此中jquery-1.9.1.min.js和jquery.i18n.properties.js文件是开源组件,直接去网上找到即可
第三个文件language.extensions.js是我们自定义的js文件,如果你将国际化的代码直接写在html页面内里,这个文件就是不用的。
2、html文件和国际化组件的初始化

这里直接引用上面示例文章内里的代码,首先必要一个切换中英文的标签,比如是一个select
  1.                         中文简体                English            
复制代码
然后是一些查看效果的html标签
  1.    
复制代码
最后就是我们必要封装的language.extensions.js文件的内容了,内里做了以下几件事:

  • 初始化页面的时候去当前域的cookie内里取当前浏览器生存语言的cookie,根据取到的当前语言版本去初始化国际化组件,然后初始化select组件的选中值
  • 注册select组件的change事件,根据当前选中的语言,更新cookie内里的语言信息,然后刷新页面。
这个文件的内容这里就不展示了,可以参考上面的使用示例文章
3、资源文件准备

根据上面的目录可以看出,我们打算将不同的语言的资源文件放到不同语言的文件夹内里,这里临时不分文件,全部的语言资源放到一个文件common.properties内里,比如内容如下:
en/common.properties
  1. searchPlaceholder=Please input serach informationsignOut=Login Outstation=Stationpartno=Part Nodescription=Descriptionquery=QuerypleaseSelect=Please Selectadd=Addedit=Editdelete=Delete
复制代码
zh-CN/common.properties
  1. searchPlaceholder=请输入关键字signOut=退出station=站点partno=零件号description=形貌query=查询pleaseSelect=请选择add=新增edit=编辑delete=删除
复制代码
貌似大功告成!当你down源码直接在google浏览器内里运行的时候你会发现一个跨域的问题。

要求你在一种webServer内里去访问.properties文件,这个问题你只必要使用任何一种webserver运行即可,比如IIS、Apache、Node的web服务器等。博主的代码是在Visual Studio内里跑的,所以是基于IIS的,当你把代码搬到VS内里跑的时候,第一个问题来了。
二、坑一:配置IIS对.properties文件的支持

如果本文仅仅是上面的内容,是没啥意义的。接下来才是本文要介绍的重点!
将上述代码直接搬到VS内里,运行的时候你会发现第一个问题:

为什么这里会请求三个properties文件?因为jquery.i18n.properties.js组件支持三种类型的命名方式,这点许多文章都有介绍,组件代码运行的时候会去请求三种规则的properties文件,只要找到任何一种规则的文件都可以读取到内里的内容。按照博主上文给出的文件目录

根据这个目录,那我们通过 http://localhost:12770/Content/i18n/zh-CN/common.properties 这个url应该能访问到zh-CN/common.properties这个文件,可现真相况确实如许:

对于这种IIS报错404的问题,C#步伐员肯定是不陌生的,无非就两个缘故原由:

  • url不正确,这个目录下面确实没有找到这个资源文件
  • 文件的类型iis默认不支持,直接拒绝请求
扫除了第一个缘故原由,那么只可能是第二个缘故原由引起的了。那么我们如何处置惩罚呢,在网上搜索半天资料,找到一种办理方案:

如许确实能绕过IIS的文件名验证,但是改源码不是一个好的办理方案,博主有一千个理由来阐明改源码的弊端。这种方式肯定不是一个最好的办理方案,于是博主决定另辟蹊径。
还记得当初博主学习less的时候,iis默认也是不支持.less文件的,于是我们在web.config内里加了如下一些配置:

这绝对属于同类型的问题,加这个配置是显式告诉IIS,我们系统内里某种后缀的文件必要哪种Processer(处置惩罚器或处置惩罚组件)去处置惩罚,受此启发,那么我们这里的.properties文件的404问题是不是也可以通过此种方式办理?如果必要通过这种思路去办理,主要问题是必要找到.properties文件的mimeType,博主思考,既然是在js内里调用这个.properties文件,那么我们是否可以使用javascript的处置惩罚机制来处置惩罚.properties文件呢,考虑到上面那种将全部.properties替换成.js的处置惩罚方式,似乎.properties和.js有许多相似之处,于是我们加上如下一条配置:

得到效果:

试验成功,就是这么简单。固然如果发布到IIS,可能必要在IIS的MIME类型内里添加.properties这种类型的映射。

好了,这个问题就这么愉快的办理了。如果你的WebServer不是基于IIS的,可能没有这个问题,但我想思路或许相通,供参考!
三、坑二:使用html的data属性初始化国际化内容

一般情况下,我们标签内里的内容如果要做国际化,必要使用 $('#id').text($.i18n.prop('proName')); 来给标签赋值,现在问题来了,我们开发一个界面,有许多地方都必要去做国际化,我们总不能如许每一个页面每一个标签通过这种方式去赋值吧,如许工作量不是一点大,于是乎博主想,有没有一种比较好的通用的办理方案去给这些必要做国际化的标签统一赋值呢。html的data属性似乎是一个不错的选择!它具有可读性强、可维护性强、兼容jquery的data()方法等优点。比如我们修改国际化组件的方法如下:
  1. jQuery.i18n.properties({        name: 'common',        path: '/Content/i18n/' + i18nLanguage + '/', //资源文件路径        mode: 'map', //用Map的方式使用资源文件中的值        language: i18nLanguage,        callback: function () {//加载成功后设置显示内容            console.log("i18n赋值中...");            try {                //初始化页面元素                $('[data-i18n-placeholder]').each(function () {                    $(this).attr('placeholder', $.i18n.prop($(this).data('i18n-placeholder')));                });                $('[data-i18n-text]').each(function () {                    //如果text内里还有html必要过滤掉                    var html = $(this).html();                    var reg = //;                    if (reg.test(html)) {                        var htmlValue = reg.exec(html)[0];                        $(this).html(htmlValue + $.i18n.prop($(this).data('i18n-text')));                    }                    else {                        $(this).text($.i18n.prop($(this).data('i18n-text')));                    }                });                $('[data-i18n-value]').each(function () {                    $(this).val($.i18n.prop($(this).data('i18n-value')));                });            }            catch(ex){ }            console.log("i18n写入完毕");        }    });
复制代码
通过data属性获取标签,然后对每个标签通过对应的data-i18n-属性进行国际化赋值即可,这里临时定义了三种类型data-i18n-placeholder、data-i18n-text、data-i18n-value的属性,如果有其他需求,可以增长其他类型。
然后看下我们html页面的使用
  1. [/code][code]
复制代码
如许不用写一句标签的赋值代码,即可对标签进行国际化。
四、坑三:第三方组件的国际化(一)

对于第三方组件,我们自定义的代码内里的中文要做国际化,我只必要使用$.i18n.prop('key')即可,比如bootstrapTable:
  1. {        field: 'AuditEventType',        title: '业务类型',        width: '12%'}
复制代码
直接使用
  1. {        field: 'AuditEventType',        title: $.i18n.prop('bllType'),        width: '12%'}
复制代码
即可。这个办理思路很简单,没啥好说的,可是有一些第三方组件,自己有国际化的功能,初始化的时候必要指定国际化的类型,形如:
  1. $(".date").datetimepicker({     format: 'YYYY-MM-DD',//日期格式化,只显示日期     locale: 'zh-CN'      //中文化});
复制代码
现在想到的办理方案,就是根据cookie内里存储的当前语言来显式赋值
  1. //获取cookie内里的语言var userLanguage = getlanguageCookie("userLanguage");$(".date").datetimepicker({     format: 'YYYY-MM-DD',//日期格式化,只显示日期     locale: userLanguage =='zh-CN'?'zh-CN':'en-US'     //国际化});
复制代码
如果是多种语言,这里可以在前端自己去处置惩罚。
五、坑四:第三方组件的国际化(二)

上面介绍了第三方组件初始化时候指定国际化,除此之外,还有别的一种情况,就是许多组件有自己的本地化(关于国际化和本地化的区别,请自行谷歌)文件,它的国际化是通过引用不同的本地化js文件来实现的,比如博主常用的bootstrapTable组件,它的目录:

还有其他组件也是如许,比如:



那么针对这种情况,我们的国际化该如何实现了,这里博主提供的思路是动态引用js,通过当前cookie内里生存的语言的类型来引用对应语言的js文件,比如针对bootstrapTable,我们如许去动态引用js
  1.      //组件根据国际化动态引入jsvar userLanguage = getlanguageCookie("userLanguage");        //如果cookie内里没有,则使用默认值        if (!userLanguage) {            userLanguage = 'zh-CN';        }        if (userLanguage == 'zh-CN') {            var script = $('<script>');            script.attr('src', '/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js');            $('body').append(script);        }        else if (userLanguage == 'en') {            var script = $('<script>');            script.attr('src', '/Content/bootstrap-table/locale/bootstrap-table-en-US.js');            $('body').append(script);        }
复制代码
如果要想代码写得更加优雅,可以自己去实现前端的抽象工厂,这里只是提供一种实现思路。
六、总结

扫除了以上几步的困难,我们的国际化在项目内里基本就能正常运行起来了,至于WebApi内里返回消息的中文,如果你也想做国际化,我们可以通过将返回消息封装,统一返回前端处置惩罚。本篇文章的“填坑方式”或许不是最好的,但至少给各人提供了一种实现思路,如果各人有更好的实现方式,接待留言交换。如果你觉得本文能够帮助你,可以右边随意 打赏 博主。
本文原创出处:http://www.cnblogs.com/landeanfen/
接待各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文毗连,否则保留追究法律责任的权利

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?用户注册

x

相关技术服务需求,请联系管理员和客服QQ:2753533861或QQ:619920289
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

帖子推荐:
客服咨询

QQ:2753533861

服务时间 9:00-22:00

快速回复 返回顶部 返回列表