Exapmple,上网导航

您现在的位置是:首页 > 快手运营 > 正文

快手运营

我爱业务网卡盟(网络爱好者卡盟)

admin2023-02-12快手运营1
  前端技术日新月异,技术栈繁多。以前端框架来说有React,Vue,Angular等等,再配以webpack,gulp,Browserify,fis等等构建工具去满足日常的开发工作。同时在

  前端技术日新月异,技术栈繁多。以前端框架来说有React, Vue, Angular等等,再配以webpack, gulp, Browserify, fis等等构建工具去满足日常的开发工作。同时在日常的工作当中,不同的项目使用的技术栈也会不一样。当需要对部分项目进行国际化改造时,由于技术栈的差异,这时你需要去寻找和当前项目使用的技术栈相匹配的国际化的插件工具。比如:

vue + vue-i18n

angular + angular-translate

react + react-intl

jquery + jquery.i18n.property

  等等,同时可能有些页面没有使用框架,或者完全是没有进行工程化的静态前端页面。

  为了减少由于不同技术栈所带来的学习相关国际化插件的成本及开发过程中可能遇到的国际化坑,在尝试着分析前端国际化所面临的主要问题及相关的解决方案后,我觉得是可以使用更加通用的技术方案去完成国际化的工作。

  国际化所面临的问题

  1.语言翻译

静态文案翻译(前端静态模板文案)

动态文案翻译(server端下发的动态数据)

  2.样式

不同语言文案长度不一样造成的样式错乱

图片的替换

  3.map表维护

  4.第三方服务

SDK

  5.本地化

货币单位

货币汇率

时间格式

  6.打包方案

运行时

编译后

解决方案

  在日常的开发过程当中,遇到的最多的需要国际化的场景是:语言翻译,样式,map表维护及打包方案。接下来针对这几块内容并结合日常的开发流程说明国际化的通用解决方案。

  首先来看下当前开发环境可能用的技术栈:

  1.使用了构建工具

webpack

gulp

fis

browserify

...

  基于这些构建工具,使用:

Vue

Angular

React

Backbone

...

未使用任何framework

  2.未使用构建工具

使用了jquery或zepto等类库

原生js

  其中在第一种开发流程当中,可用的国际化的工具可选方案较多:

  从框架层面来看,各大框架都会有相对应的国际化插件,例如:vue-i18n, angular-translate, react-intl等,这些插件可以无缝接入当前的开发环节当中。优点是这些框架层面的国际化插件使用灵活,可以进行静态文案的翻译,动态文案的翻译。缺点就是开发过程中使用不同的框架还需要去学习相对应的插件,存在一定的学习成本,同时在业务代码中可能存在不同语言包判断逻辑。

  从构建工具层面来看, webpack有相对应的i18n-webpack-plugin, gulp有gulp-static-i18n等相应的插件。这些插件的套路一般都是在你自定义map语言映射表,同时根据插件定义好的需要被编译的代码格式,然后在代码的编译阶段,通过字符串匹配的形式去完成静态文案的替换工作。这些插件仅仅解决了静态文案的问题,比如一些样式,图片替换,class属性,以及动态文案的翻译等工作并没有做。

  事实上,这些插件在编译过程中对于样式,图片替换, class属性等替换工作是非常容易完成的,而动态文案的翻译因为缺少context,所以不会选择使用这些编译插件去完成动态文案的翻译工作。相反,将动态文案的翻译放到运行时去完成应该是更加靠谱的。

  但是换个角度,抛开基于这些构建工具进行开发的框架来说,构建工具层面的国际化插件可以很好的抹平使用不同框架的差异,通过将国际化的过程从运行时转到编译时,在编译的过程中就完成大部分的国际化任务,降低学习相对应国际化插件的成本,同时在构建打包环节可实现定制化。不过也存在一定的缺点,就是这些构建工具层面的国际化插件只能完成一些基本的静态文案的翻译,因为缺少context,并不能很好的去完成动态文案的翻译工作,它比较适用于一些纯静态,偏展示性的网页。

  在第二种开发流程当中,可使用的国际化工具较少,大多都会搭配jquery这些类库及相对应的jquery.i18n或i18next等插件去完成国际化。

  综合不同的构建工具,开发框架及类库,针对不同的开发环境似乎是可以找到一个比较通用的国际化的方案的。

  这个方案的大致思路就是:通过构建工具去完成样式, 图片替换, class属性等的替换工作,在业务代码中不会出现过多的因国际化而多出的变量名,同时使用一个通用的翻译函数去完成静态文案及动态文案的翻译工作,而不用使用不同框架提供的相应的国际化插件。简单点来说就是:

我爱业务网卡盟(网络爱好者卡盟)

依据你使用的构建工具 + 一个通用的翻译函数去完成前端国际化

  首先,这个通用的语言翻译函数: di18n-translate。它所提供的功能就是静态和动态文案的翻译, 不依赖开发框架及构建工具。可见demo

  npm install di18n-translate // 模块化写法constLOCALE = 'en'constDI18n = require( 'di18n-translate') constdi18n = newDI18n({ locale: LOCALE, // 语言环境 isReplace: false, // 是否进行替换(适用于没有使用任何构建工具开发流程) messages: { // 语言映射表 en: { 你好: 'Hello, {person}'}, zh: { 你好: '你好, {person}'} } }) di18n.$t( '你好', {person: 'xl'}) // 输出: Hello, xl// 外链形式< src= "./lib/di18n-translate/index.js"> </><>constLOCALE = 'en'constdi18n = newDI18n({ locale: LOCALE, isReplace: false, messages: { // 语言包} }) </>

  这个时候你只需要将这个通用的翻译函数以适当的方式集成到你的开发框架当中去。

  静态/动态文案翻译的问题解决了,国际化还有一个比较重要的地方就是样式问题,比如中文转英文后肯定会遇到文案过长的情况。那么可能需要精简翻译,使文案保持在一定的可接受的长度范围内。但是大部分的情况都是文案在保持原意的情况下无法再进行精简。这时必须要前端来进行样式上的调整,那么可能还需要设计的同学参与进来,对一些文案过多出现折行的情况再单独做样式的定义。在细调样式这块,主要还是通过不同的语言标识去控制不同标签的class,来单独定义样式, 以及不同语言环境下的图片替换工作。

  // 中文环境<p class= "desc"> </p>// 英文环境下 <pclass="desc en"></p>// 日文环境下 <pclass="desc jp"></p>

  在使用framework的情况下,framework一般都帮你做好了view层的渲染工作,那么你可以在代码当中轻松的通过代码去控制class的内容, 以及不同语言环境下的图片替换工作。

  例如vue:

  <template> <pclass="desc":class="locale"// locale这个变量去控制class的内容 :style="{backgroundImage: 'url(' + bgImg + ')'}"></p><img:src="imgSrc">// imgSrc去控制图片路径 </template><>export default{ name: 'page', data () { return{ locale: 'en', imgSrc: require('./img/demo.png'), bgImg: './img/demo.png'} } } </>

  这个时候,你的业务代码中会多出很多这些关于语言环境的变量。

  针对这个问题,我希望是在构建工作中去完成语言环境的配置,而不是将这个配置放到业务代码当中。

  所以如果你是使用webpack进行构建的,那么可以使用locale-path-loader这个preloader

  它所做的工作之一是在文件编译阶段,就完成语言环境的配置工作,在你的业务代码中不会出现过多的关于语言环境变量以及很好的解决了运行时作为css的background的图片替换工作

  图片路径替换 源文件 <img src= "/static/images/${locale}/loader.png"/> 编译后 <img src= "/static/images/en/loader.png"/>css文件中图片路径替换 源文件 .box { background: url( '/static/images/${locale}/loader.png') } 编译后 .box { background: url( '/static/images/en/loader.png') } class属性: 源文件 <p class= "box ${locale}"> 编译后 <p class= "box en">

  这个loader还提供了另外的一个功能,提供了一种维护map的方式,当前大多数map表的维护工作是单独新建不同语言环境的文件夹:

  |--lang | | | |--en.json | |--zh.json | |--jp.json

  开发环节中,你需要在不同的json文件中去切换,完成map表的维护。

  这个loader还提供了另外一个功能.就是在你开发目录中任意位置去写语言的映射表,而通过这个preloader去将散落在不同文件的语言映射表遍历出来,并生成一个总的语言表:

  在模板文件中: <!--<i18n> { "我爱你": { "en": "I love you", "zh": "我爱你" } } <i18n>-->在js文件中: /*<i18n>{ "你好": { "en": "Hello", "zh": "你好" } } <i18n>*/

  最后通过这个preloader去遍历文件并根据配置路径生成最终的语言包lang.json:

  { "en": { "我爱你": "I love you", "你好": "Hello"}, "zh": { "我爱你": "我爱你", "你好": "你好"}}

  loader使用方法:

  npm install locale-path-loader

  参数说明:

locale: String 当前开发环境中语言包配置, 默认为zh, 完成图片,css,class属性的替换工作

我爱业务网卡盟(网络爱好者卡盟)

inline: Boolean 是否启用内联模式,即使用就近原则,map表分散在各文件中,由loader去遍历生成最终的map表

outputDir: String 最终lang.json语言映射表生成的路径配置(如果开启了inline模式需要对此参数进行配置)

  以vue为例:

  webpack 1.x 配置:

  module.exports = { .... preLoaders: [ { test: /.*$/, exclude: /node_modules/, loaders: [ 'eslint', 'locale-path?outputDir=./src/common&locale=en&inline=true'] } ] .... }

  webpack 2 配置:

  module.exports = { .... module: { rules: [{ test: /.*$/, enforce: 'pre', exclude: /node_modules/, use: [{ loader: 'locale-path-loader', options: { locale: 'en', outputDir: './src/common', inline: true} }] }] } .... }

  如果使用gulp作为构建工具,可以使用gulp-locale-path(还没写- -)这个插件去完成同样的功能.

  到这里先简单总结下,在使用构建工具并搭配framework进行开发时,通过构建工具完成图片,css,及class属性的路径替换工作,同时使用上文提供翻译函数基本上可以满足那些基于构建工具,但是不管是否使用framework的前端国际化的工作了

  接下来说说没有使用构建工具,偏静态展示性网页的国际化。

  这个时候你可能没用hot reload或者live reload,也没有构建工具帮你完成变量的替换工作。那么在开发环境中如何同时进行不同语言环境的开发工作呢?

  在上文提到的di18n-translate包中,除了提供了翻译函数外:

  constDI18n = require( 'di18n-translate') constdi18n = newDI18n({ locale: 'en', // 语言环境isReplace: false, // 是否进行替换(适用于没有使用任何构建工具开发流程)messages: { // 语言映射表en: { 你好: 'Hello, {person}'}, zh: { 你好: '你好, {person}'} } }) // 有参数di18n.$t( '你好', {person: 'xl'})

  其中当isReplace字段设为true时会开启dom替换模式,代码中插入的这一段js,用以替换class, img, 静态文案等内容, 如下:

  通过属性配置: <pi18n-class="i18n">i18n-Class</p><imgsrc=""i18n-img="./imgs/${locale}/header-img.png"width="50"height="50"><divi18n-content="你好"></div><inputtype="text"i18n-placeholder="你好">

  di18n函数会通过属性选择器,将相对应的dom元素中需要做国际化的内容进行替换,

  最后得到的结果是

  <p class= "i18n">i18n-Class< /p> <img src="./imgs/en/header-img.png " width="50" height="50"> <div>你好</div> <input type="text " placeholder="你好 "> 需要动态翻译的内容就借助实例化的di18n.$t进行处理 di18n.$t('你好', {person: 'xl'}) //输入: 你好, xl

  以上就是在开发环节,使用不同技术栈的情况下一种更加通用的前端国际化方案。

  最后说下打包环节的处理:

  最终打包有2种方案:

不分语言环境最后打包到一个包中,翻译功能,图片替换, css路径,class属性等通过运行时进行处理, 后端只需要下发语言标识字段,前端通过语言标识字段去完成不同语言环境下的页面渲染工作

分语言环境将源文件最终编译到不同语言环境下,不同语言环境对应于不同的最后的包,虽然最终有不同语言版本的包,但是只需要维护同一份代码, 最后可能打包出来的目录结构是:

|--deploy | | | |---en | | |--app.js | | |--vendor.js | | |--index.html | |---zh | | |--app.js | | |--vendor.js | | |--index.html | |---jp | | |--app.js | | |--vendor.js | | |--index.html | |----lang.json

  不过这个方案需要服务端做一定的支持,根据不同语言环境请求,返回相对应的入口文件.这种分包打包方案的demo可以参见/vue-demo文件

  DEMOS:

基于webpack使用vue进行开发的demo,请参见/vue-demo文件夹

不使用构建工具,偏纯静态页面展示的demo,请参见/html-demo文件夹

  福利!免费领取腾讯高级讲师网页设计教程

点我领取

  来源:segmentfault

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~