本文章共3470字,预计阅读时间5-10分钟。

国际化-前言

每个开发者能希望编写的程序可以让全世界的用户使用,它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换种说法,「应用程序」的功能和「代码设计」时考虑在不同地区运行的需要,其代码适应不同区域要求。开发这样的的过程,就称为国际化( internationalization),简称i18n。

i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。

在全球化的时代,国际化尤为重要,因为产品的潜在用户可能来自世界的各个角落!

国际化-范围

国际化与本地化工作的焦点包括但不限于如下:

语言

  • 不同国家的语言;
  • 文字书写方向;(比如德语是从左到右,而波斯语、希伯来语和阿拉伯语是由右到左。)
  • 图片中包含的文字;
  • 程序中的音频;
  • 程序中的视频字幕;

文化

  • 图片和颜色:这牵涉到理解和文化适宜的议题;
  • 名字和称谓;
  • 政府给定的编码(如美国的社会安全码,英国的National Insurance number,爱沙尼亚的Isikukood及其它各国的身份证号码)和护照;
  • 电话号码前缀、地址和国际邮递区号;
  • 货币 (符号、货币标志的位置);
  • 长度、容积、重量单位;
  • 标准纸张大小;

书写习惯

  • 日期跟时间的格式,包含各式日历。
  • 时区(在国际场合会使用世界标准时间)
  • 数字格式(小数点、分隔点的位置、分隔所用的字符)

产品和服务所要面向的法规

程序的内容、运营方式及方向需要遵守当地法律、法规;

多语言翻译方案

目前,并没有非常完美,适用所有情况的多语言方案,所以找到一个比较契合自己团队的方案,并做一系列配制方法去用,是比较耗时的一项工程。「是否需要花时间成本来做到前端国际化,完全取决分析自身团队的需求。」

使用插件在线翻译

随着全球化网络时代的到来,语言障碍已经成为二十一世纪社会发展的重要瓶颈,实现任意时间、任意地点、任意语言的无障碍自由沟通是人类追求的一个梦想。这仅是全球化背景下的一个小缩影。在社会快速发展的进程中,在线翻译扮演越来越重要的角色。

运行规则

将单词序列(一个或多个句子)作为输入,并生成单词的输出序列,这是通过递归神经网络(RNN)实现的。具体来说,就是让两个将与某个特殊令牌一起运行的递归神经网络尝试根据前一个序列来预测后一个状态序列。

它主要由编码器和解码器两部分构成,因此有时候被称为编码器-解码器网络。

· 编码器:使用多个深度神经网络层,将输入单词转换为相应的隐藏向量。每个向量代表当前单词及其语境。

· 解码器:与编码器类似。它将编码器生成的隐藏向量、自身的隐藏状态和当前单词作为输入,从而生成下一个隐藏向量,最终预测下一个单词。

谷歌插件在线翻译

谷歌不再提供对 Google 翻译的网站翻译器的新访问。此更改不会影响网站翻译器的现有使用。

谷歌鼓励希望翻译网页的用户使用支持本地翻译的浏览器。

效果图示例:

代码示例

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Translate</title>
</head>
<body>
    <p>你好 世界!</p>
    <!--谷歌翻译 -->
    <!--    如需隐藏/更改一些样式,可使用css操作-->
    <div id="google_translate_element"></div>
</body>
<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
<script>
  function googleTranslateElementInit() {
    new google.translate.TranslateElement({
      // includedLanguages: 'de,en,es,fr,it', 需要下拉翻译支持哪些语言,默认全部
      layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL
    }, 'google_translate_element');
  }
</script>
</html>

在线示例/源码地址

在线示例:点此查看- 谷歌插件在线翻译(需要可以访问google)

源码地址:https://github.com/Tzlibai/Demo/tree/master/i18n/google

注:目前浏览器基本都内置了- 网页在线翻译功能**

PS: 谷歌翻译插件会在替换文本时修改标签(DOM结构)会导致Vue、React这种基于virtual dom的框架产生问题

问题:难以避免的误差

机器翻译其误差在所难免,原因在于,机器翻译运用语言学原理,机器自动识别语法,调用存储的词库,自动进行对应翻译,但是因语法、词法、句法发生变化或者不规则,出现错误是难免的,比如《大话西游》中**“给我一个杀你的理由,先”**中,“先”字意义上其实是起修饰限制作用,但在机器翻译时就会有不同的意思。

机器毕竟是机器,没有人对语言的特殊感情。它怎么会感受“「万里悲秋常作客,百年多病独登台」”的无限悲凉之意?毕竟汉语因其词法、语法、句法的变化及其语境的更换,其意思大相径庭。

维护多套页面/语言代码

顾名思义:**不同语言编写不同的页面。**假设需要支持3种语言,此时需要编写三种不同的页面,这样的弊端是当页面需要维护修改时,需要对不同的页面进行更改

效果图示例:

在线示例/源码地址

在线示例:点此查看- 维护多套页面/语言代码

源码地址:https://github.com/Tzlibai/Demo/tree/master/i18n/more

语言包配置文件

将所有的「语言资源放在独立的文件夹下」,以每个字段「唯一标识」,去找到不同语言相对应的字段,以显示来完成前端国际化。
这样在html我们只需要输出标识符,在js中配置好功能、路径,我们就可以让它自行去语言资源包中找到对应语言字段以显示。

jQuery - 多语言翻译

代码示例

「主要步骤如下:」

  • jquery.js文件

  • jquery.i18n.properties.js文件

  • 各个国家语言包(.properties格式文件,每个国家语言包目录下都会有该文件,只是配置不同)

    // commion.properties 文件格式如下
    // (key) = (value) hi=Hello world!
  • index 编写逻辑,读写cookie、引入语言包、根据class渲染文案

整理完成后 目录如下图:

「html文件如下:」

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
<!--    这里是设置id为i18n_pagename, 引入了资源文件common-->
    <meta id="i18n_pagename" content="common">
    <title>jQuery - 多语言翻译</title>
</head>
<body>
<!--  这里面class=”i18n”写法,下边在js里面我们可以根据类选择器获取需要国际化的地方,-->
<!--  然后name=”hi”这里面的 hi 跟我们语言包里面资源文件里面的key保持一致-->
    <label class="i18n" name="hi"></label>
    <br>
<!--切换按钮-->
    <select id="language">
        <option value="zh-CN">中文</option>
        <option value="en">英语</option>
        <option value="idn">印尼语语</option>
    </select>
</body>
<script src="./i18n/jquery.js"></script>
<script src="./i18n/jquery.i18n.properties.js.js"></script>
<script>
  /**
   * cookie操作
   */
  var getCookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
      options = options || {};
      if (value === null) {
        value = '';
        options.expires = -1;
      }
      var expires = '';
      if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
        var date;
        if (typeof options.expires == 'number') {
          date = new Date();
          date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
        } else {
          date = options.expires;
        }
        expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
      }
      var path = options.path ? '; path=' + options.path : '';
      var domain = options.domain ? '; domain=' + options.domain : '';
      var s = [cookie, expires, path, domain, secure].join('');
      var secure = options.secure ? '; secure' : '';
      var c = [name, '=', encodeURIComponent(value)].join('');
      var cookie = [c, expires, path, domain, secure].join('')
      document.cookie = cookie;
    } else { // only name given, get cookie
      var cookieValue = null;
      if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
          var cookie = jQuery.trim(cookies[i]);
          // Does this cookie string begin with the name we want?
          if (cookie.substring(0, name.length + 1) == (name + '=')) {
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
          }
        }
      }
      return cookieValue;
    }
  };

  /**
   * 获取浏览器语言类型
   * @return {string} 浏览器国家语言
   */
  var getNavLanguage = function(){
    if(navigator.appName == "Netscape"){
      var navLanguage = navigator.language;
      return navLanguage.substr(0,2);
    }
    return false;
  }

  /**
   * 设置语言类型: 默认为中文
   */
  var i18nLanguage = "zh-CN";
  /*
  设置一下网站支持的语言种类
   */
  var webLanguage = ['zh-CN', 'idn', 'en'];

  /**
   * 执行页面i18n方法
   * @return
   */
  var execI18n = function(){
    /*
    获取一下资源文件名
     */
    var optionEle = $("#i18n_pagename");
    if (optionEle.length < 1) {
      console.log("未找到页面名称元素,请在页面写入\n <meta id=\"i18n_pagename\" content=\"页面名(对应语言包的语言文件名)\">");
      return false;
    };
    var sourceName = optionEle.attr('content');
    sourceName = sourceName.split('-');
    /*
    首先获取用户浏览器设备之前选择过的语言类型
     */
    if (getCookie("userLanguage")) {
      i18nLanguage = getCookie("userLanguage");
    } else {
      // 获取浏览器语言
      var navLanguage = getNavLanguage();
      if (navLanguage) {
        // 判断是否在网站支持语言数组里
        var charSize = $.inArray(navLanguage, webLanguage);
        if (charSize > -1) {
          i18nLanguage = navLanguage;
          // 存到缓存中
          getCookie("userLanguage",navLanguage);
        };
      } else{
        console.log("not navigator");
        return false;
      }
    }
    /* 需要引入 i18n 文件*/
    if ($.i18n == undefined) {
      console.log("请引入i18n js 文件")
      return false;
    };

    /*
    这里需要进行i18n的翻译
     */
    jQuery.i18n.properties({
      name : sourceName, //资源文件名称
      path : 'i18n/' + i18nLanguage +'/', //资源文件路径
      mode : 'map', //用Map的方式使用资源文件中的值
      language : i18nLanguage,
      callback : function() {//加载成功后设置显示内容
        var insertEle = $(".i18n");
        console.log(".i18n 写入中...");
        insertEle.each(function() {
          // 根据i18n元素的 name 获取内容写入
          $(this).html($.i18n.prop($(this).attr('name')));
        });
        console.log("写入完毕");

        console.log(".i18n-input 写入中...");
        var insertInputEle = $(".i18n-input");
        insertInputEle.each(function() {
          var selectAttr = $(this).attr('selectattr');
          if (!selectAttr) {
            selectAttr = "value";
          };
          $(this).attr(selectAttr, $.i18n.prop($(this).attr('selectname')));
        });
        console.log("写入完毕");
      }
    });
  }

  /*页面执行加载执行*/
  $(function(){
    /*执行I18n翻译*/
    execI18n();
    /*将语言选择默认选中缓存中的值*/
    $("#language option[value="+i18nLanguage+"]").attr("selected",true);
    /* 选择语言 */
    $("#language").on('change', function() {
      var language = $(this).children('option:selected').val()
      console.log(language);
      getCookie("userLanguage",language,{
        expires: 30,
        path:'/'
      });
      location.reload();
    });
  });
</script>
</html>

如打开文件遇到跨域、403、第三方组件需要国际化问题可参考:jquery.i18n国际话及问题整理 - 隔壁丿老苏

在线示例/源码地址

在线示例:点此查看- jQuery - 多语言翻译

源码地址:https://github.com/Tzlibai/Demo/tree/master/i18n/jquery

Vue - 多语言翻译

Vue I18n 是 Vue.js 的国际化插件。它可以轻松地将一些本地化功能集成到你的 Vue.js 应用程序中。

由于官方文档表述的已经十分详细,这里就不做赘述;

该插件的解决方案也是基于「多个国家配置不同的语言文案」,通过对应key动态渲染。

React - 多语言翻译

i18next 不仅仅是提供标准的 i18n 功能,例如(复数、上下文、插值、格式)。它为您提供了一个完整的解决方案,将您的产品从 Web 本地化到移动设备和桌面。

由于官方文档表述的已经十分详细,这里也就不做赘述;

该插件的解决方案也是基于「多个国家配置不同的语言文案」,通过对应key动态渲染。

番外

:lang选择器

:lang() CSS 伪类基于元素语言来匹配页面元素。:lang() 伪类选择器并不那么出名。但是,此伪类选择器非常酷,因为即使在元素外部声明了语言,它也可以根据 lang 属性识别内容的语言。

// html
<div lang="en"><q>This English quote has a <q>nested</q> quote inside.</q></div>
<div lang="fr"><q>This French quote has a <q>nested</q> quote inside.</q></div>
<div lang="de"><q>This German quote has a <q>nested</q> quote inside.</q></div>

// css
:lang(en) > q { color: red; }
:lang(fr) > q { color: blue; }
:lang(de) > q { color: pink; }

参考资料

结尾

好了,以上就是本篇全部文章内容啦。

如果遇到问题或者有其他意见可以在下方评论区贴出!

码字不易。如果觉得本篇文章对你有帮助的话,希望你可以留言点赞支持一下,非常感谢~

只要有树叶飞舞的地方,火就会燃烧,火的影子照耀着村子,新的树叶就会发芽。

jquery/vue/react前端多语言国际化翻译方案指南的更多相关文章

  1. 基于Vue/React项目的移动端适配方案

    本文的目标是通过下文介绍的适配方案,使用vue或react开发移动端及H5的时候,不需要再关心移动设备的大小,只需要按照固定设计稿的px值布局,提升开发效率. 下文给出了本人分别使用create-re ...

  2. 循序渐进VUE+Element 前端应用开发(9)--- 界面语言国际化的处理

    我们开发的系统,一般可以不用考虑语言国际化的问题,大多数系统一般是给本国人使用的,而且直接使用中文开发界面会更加迅速 一些,不过框架最好能够支持国际化的处理,以便在需要的时候,可以花点时间来实现多语言 ...

  3. 2015前端各大框架比较(angular,vue,react,ant)

    前端流行框架大比拼 angular vue react ant-design angularjs angular是个MVVM的框架.针对的是MVVM这整个事.angular的最主要的场景就是单页应用, ...

  4. 前端三大框架(Angular Vue React)

    前端,HTML(超文本标记语言),CSS(层叠样式表)和JavaScript(脚本语言) HTML,通常说的h5,其实按标准来说,HTML4的后续版本不带编号了,并保证向前的兼容性 CSS的版本3,增 ...

  5. 基于jQuery.i18n.properties实现前端网站语言多版本

    我是参考播客做了个demo:http://blog.csdn.net/aixiaoyang168/article/details/49336709 jQuery.i18n.properties采用.p ...

  6. 从DOM操作看Vue&React的前端组件化,顺带补齐React的demo

    前言 接上文:谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo 上次写完博客后,有朋友反应第一内容有点深,看着迷迷糊糊:第二是感觉没什么使用场景,太过业务化,还不如直接写Vue ...

  7. 前端开发组件化设计vue,react,angular原则漫谈

    前端开发组件化设计vue,react,angular原则漫谈 https://www.toutiao.com/a6346443500179505410/?tt_from=weixin&utm_ ...

  8. 三种Web前端框架比较与介绍--Vue, react, angular

    一.Angular 1.MVVM(Model)(View)(View-model): 2.模块化(Module)控制器(Contoller)依赖注入: 3.双向数据绑定:界面的操作能实时反映到数据,数 ...

  9. VUE实现Studio管理后台(三):支持多语言国际化(vue-i18n)

    RXEditor的第一版本是英文版,有些朋友看起来觉得不习惯,后来因为惰性,不愿意再修改旧代码加入中文版,这次提前就把这个问题解决了,克服惰性最好的方式,就是想到就尽快去做,避免拖延. 本来计划在界面 ...

随机推荐

  1. odoo中接口开发

    文章参考:https://blog.csdn.net/qq_33472765/article/details/81913627案例0000001接口调用请求说明:https请求方式:GET(请使用ht ...

  2. SpringBoot自动装配-源码分析

    1. 简介 通过源码探究SpringBoot的自动装配功能. 2. 核心代码 2.1 启动类 我们都知道SpringBoot项目创建好后,会自动生成一个当前模块的启动类.如下: import org. ...

  3. IDEA创建Mapper.xml文件识别不成功的问题

    在IDEA的maven项目中,创建一个EmpMapper.xml的文件识别不成功,图标显示为文本文档类型,在写代码时也不会弹出提示 解决方法: 在文件->设置->编辑器->文件类型中 ...

  4. Java数组07——稀疏数组

    稀疏数组 总结: 记录有效的坐标: 记录原始做表的大小和有效值的个数 记录每一个有效值的坐标 ,变成一个新的数组 age:  package array; ​ public class ArrayDe ...

  5. 3D性能优化 | 说一说glTF文件压缩

    引言 最近做T级互动,需要使用到3D模型.相信大家和我一样,在开始着手的时候,一定会有这么些问题: 1.如何选择3D模型的导出格式 2.如何对模型文件进行优化 3.在大流量的项目中兼容性怎么样 让我们 ...

  6. 十分钟带你了解CANN应用开发全流程

    摘要:CANN作为昇腾AI处理器的发动机,支持业界多种主流的AI框架,包括MindSpore.TensorFlow.Pytorch.Caffe等,并提供1200多个基础算子. 2021年7月8日,第四 ...

  7. sqli-labs lesson 7-10 (文件导出,布尔盲注,延时注入)

    写在前面: 首先需要更改一下数据库用户的权限用于我们之后的操作. 首先在mysql命令行中用show variables like '%secure%';查看 secure-file-priv 当前的 ...

  8. java JNI介绍

    java JNI介绍 目录 java JNI介绍 1. Java调用C++代码 2.C++代码调用java代码 JNI是Java Native Interface的全称. oracle文档中是这样描述 ...

  9. STM32—驱动HC-SR04超声波测距模块

    文章目录 超声波测距原理 HC-SR04工作原理 STM32实现驱动 1.引脚的配置 2.时序控制 3.时间差测量 4.如何将距离测出来 超声波测距原理 利用HC-SR04超声波测距模块可以实现比较精 ...

  10. LNMP 方式部署 zabbix 5.0

    文章链接 Zabbix 5.0 LTS新增功能 新版本附带了可用性,安全性和完整性方面的重大改进列表.Zabbix团队遵循的主要策略是使Zabbix尽可能可用.Zabbix是一种开源,免费的监视解决方 ...