App开发——国际化多语言的实现

news2024/11/19 0:33:02

1.引言

我们当前正处于一个全球化的世界,所以我们开发的 App 也会有很大的概率,需要满足国际化多语言的需求。今天刚好看到有个小伙伴遇到了这个需求需要实现,这里就借此机会,简单讲解一下,在 YonBuilder移动开发 技术中,如果去实现一个支持国际化多语言的 App 应用开发。

2.开发思路逻辑

多语言国际化,说白了就是将页面的文字内容显示为指定的国家语音。根据这个核心诉求,我们可以将整体功能拆分成以下的几个功能点需求:

2.1包含多语言内容的资源文件

这个是物料基础,用于切换到对应的语言后,可以正确的显示对应内容

2.2页面使用模板渲染构建

可以使用vue、react或者doT等模板渲染框架,目的是一旦切换了系统语言后,页面可以动态的进行快速切换

2.3编写多语言切换逻辑

包括获取当前多语言版本、设置多语言版本、读取多语言版本、读取多语言内容、页面实时渲染等逻辑

3实战演练:一个简单的多语言Demo

3.1创建一个应用项目

PS: 还未学习创建的新手同学,可跳转【2023最新】超详细图文保姆级教程:App开发新手入门(1),进行基础学习后再回来继续。

创建一个应用,并在本地使用 YonStudio 开发工具打开

在这里插入图片描述

3.2创建一个页面,用于多语言内容展示

我们直接修改 ./html/main.html 页面,下面仅讲解涉及的主要功能代码,全部代码可去我的gitee仓库:https://gitee.com/T0T/yonbuilder-app-demos下载。

说明:本页面的数据绑定实现方式是通过引用 vue 框架来实现的,将最新的 vue.js 代码下载到本地j进行保存, 本次演示引用的是 vue3 框架代码

https://unpkg.com/vue@3.4.14/dist/vue.global.prod.js

PS: 通过 src 直接引用 cdn 链接也是可以的,不过在实际开发中,因为网络网速的原因,还是放在本地直接引用的方式,运行效率会更好。

在这里插入图片描述

页面内通过 script 标签引用 vue 文件

<head>
    <script src="../script/vue.global.prod.js"></script>
    <style>
        html,body {
            height: 100%;
            width: 100%;
        }
        ....代码省略
    </style>
</head>

编写页面内容,对于需要做国际化的文字内容,使用模板变量来进行标识,及 下面代码块中的 {{ }},这些是vue的基本语法规则,这里就不多说了。

<body id="app">
    <div class="panel">
        <div class="title">{{ title }}</div>
        <div class="row">
            <span class="row-label">{{ nameLabel }}:</span>
            <span class="row-content">{{ name }}</span>
        </div>
        <div class="row">
            <span class="row-label">{{ ageLabel }}:</span>
            <span class="row-content">{{ age }}</span>
        </div>
    </div>
    <div class="panel" style="margin-top: 50px;">
        <div class="title">多语言切换操作</div>
        <div class="flex-row">
            <div class="btn" tapmode="cilck-active" :class="{active: i18nKey==='zh-CN'}" @click="handleSetI18n('zh-CN')">中文</div>
            <div class="btn" :class="{active: i18nKey==='en-US'}" tapmode="cilck-active" @click="handleSetI18n('en-US')">英文</div>
        </div>
    </div>
</body>

在运行逻辑部分,我们先初始化 vue 示例对象,然后在 生命周期事件 mounted 方法内,调用内部的 initPageWithVue() 方法进行页面的初始化逻辑操作。

// 页面内容国际化
addI18nChangeListener(this.parsePageWithI18n);
this.parsePageWithI18n();

上面代码实现了2个业务功能

  • 国际化语音切换时间监听

addI18nChangeListener 方法是添加了国际化语音切换的事件监听,当在其他页面切换语言后,当前页面通过该监听获取该事件,然后即可调用 parsePageWithI18n 方法,进行页面内容的国际化切换。
该方法是封装在 i18n.js 文件内,当前页面通过 script 脚本方式引入,具体的内容,等后面我们讲解 i18n.js 文件时再展开。

<script type="text/javascript" src="../script/i18n.js"></script>
  • 页面内容进行初始的国际化处理

parsePageWithI18n 方法,主要逻辑是负责将当前页面的内容,转化成当前正在使用的国际化语言内容。

对当前页面的文本内容进行初始变量值的国际化处理,可以看到在 parsePageWithI18n 方法中,我们通过调用 parseWord 函数,对文本内容进行国际化内容转换。这个 parseWord 函数也是我们自己编写后封装在 i18n.js 文件中的,后面我们会做详细介绍。

 parsePageWithI18n() {
    this.i18nKey = getI18n();
    this.title = parseWord('人物简介');
    this.nameLabel = parseWord('姓名');
    this.name = parseWord('张三');
    this.ageLabel = parseWord('年龄');
}

当前页面我们还设置了一个切换国际化语音的方法 handleSetI18n,用于模拟实际业务中的国际化语音切换。

handleSetI18n(i18nSign){
    if(!i18nSign) return;
    setI18n(i18nSign);
}

在实际业务中,根据产品需求,有可能在 App 应用中,显示的提供语言切换按钮,像本次 App 这样。也有可能直接获取手机操作系统的本地语言,然后 App 进行动态的适配。原来大致都是一样的,获取操作系统的本地语言,可以使用引擎提供的 api.language 方法

在这里插入图片描述

3.3编写多语言逻辑脚本文件

我们需要根据页面中需要进行国际化的语言内容,进行整理,然后编写一个最终版本的 国际化资源文件。当然此方法并不是唯一的实现逻辑,我们也可以根据需要,将文件内容按不同的维度拆分成多个文件进行相应的读取处理,这里我们主要讲解基本的实现思路,就不进行过多的扩展了。

我们实际 demo 应用中的 ./script/i18n.js 文件,就是我们最终封装的国际化多语言服务脚本。其中我们主要定义了以下几个主要的功能逻辑。

    1. 多语言映射数据体

根据实际业务需要,我们可以增加自己的多语言适配版本。

PS: 当前使用中文内容作为 map 中的 key,主要是为了方便在具体的引用页面中,可以直观的了解当前的文本内容的含义。开发者也可以使用英文或其他文本内容作为标识,这个并不强制唯一。

var i18nMapData =  {
        '多语言国际化示例': {
            'zh-CN': '多语言国际化示例',
            'en-US': 'i18n Demo'
        },
        '人物简介': {
            'zh-CN': '人物简介',
            'en-US': 'profile'
        },
        '姓名': {
            'zh-CN': '姓名',
            'en-US': 'name'
        },
        '张三': {
            'zh-CN': '张三',
            'en-US': 'three'
        },
        '年龄': {
            'zh-CN': '年龄',
            'en-US': 'age'
        },
    }
    1. 获取当前应用的多语言版本标识

PS: 数据的本地化存储有多重方式,本处代码中,使用 api.setPrefsapi.getPrefs 函数方法进行数据的本地化存储读取的主要原因是 api.getPrefs 函数方法支持同步读取(及下面代码的 sync: true ),大多数的本地读取是异步的,如果开发者经验不足,容易产生一些不必要的逻辑错误。

/**
 * 读取国际化语言的判断标识(采用同步策略)
 * @returns 
 */
function getI18n() {
    var i18nStr = api.getPrefs({
        sync: true,
        key: 'i18n'
    });
    if(!i18nStr) {
        i18nStr = api.language;
        setI18n(i18nStr);
    }
    return i18nStr;
}
    1. 设置当前应用的多语言版本标识

这里我们在进行本地设置的同时,向外部发送了一个 i18nChange 的消息事件,主要的目的帮助已经加载完毕的页面,通过监听该事件,实现页面内容的动态国际化切换。

/**
 * 存储国际化语言的判断标识
 * @param {String} i18nSign 
 */
function setI18n(i18nSign) {
    // 新的系统语言标识
    var i18nStr = i18nSign ? i18nSign : api.language;
    // 本地缓存
    api.setPrefs({
        key: 'i18n',
        value: i18nStr
    });
    // 发送同步通知,用于一些已经初始化的页面进行动态切换(按业务需要,非必须)
    api.sendEvent({
        name:'i18nChange',
        extra: {
            i18nSign: i18nStr
        }
    })
}
    1. 国际化多语言切换的事件监听逻辑封装

需要国际化的页面,通过调用本方法,即添加了事件监听。页面通过将自己内部的国际化处理函数传入当前方法,当事件触发时,通过回调机制触发函数执行,从而实现了自动化的国际化内容处理。

/**
 * 添加i18n改变的页面监听
 * @param {Function} callBack 触发事件后的回调函数
 */
    
function addI18nChangeListener(callBack) {
    api.addEventListener({
        name:'i18nChange'
    }, function(ret){
        if(typeof callBack === 'function') {
            callBack(ret.value);
        }
    })
}

3.4最终呈现的效果

在这里插入图片描述

4.总结

以上只是一个简单的多语言Demo,意在示范整体的实现思路逻辑,在实际的应用开发中,开发者需要根据实际的业务逻辑进行相应的变通修改。

比如上面只是展示了页面内的静态内容的替换,那么对于一些交互的提示信息等动态内容并未展示。其实他们的内在逻辑是一样的,就是在内容展示的前一个周期内,将需要展示的文字内容动态替换为对应的语言内容即可。

另外我们在实际开发中,会向后端服务器发送请求,接收服务端的响应数据,并根据业务逻辑进行展示(正确的提示或者错误的提示等)。如果客户端展示的内容是由服务端提供的,那么这里有2种实现方式。

一种是前端将当前系统语音版本信息发送给服务端,由服务端负责返回对应的多语言内容;
另一种是将服务端返回的提示信息整理成固定的多语言版本文件,然后存储到前端应用中,由前端自行完成语言切换;

这两种方法都OK,具体实践中可以由前后端的开发人员一起沟通确定即可。

其他的比如切换系统语言后,如何实现页面的实时刷新,这里我们可以使用 事件监听或者跨页面执行脚本等支持消息传递的方法去实现事件触发即可。

注意事项: 因为各语种同一个意思的文字长度不相同,有的会很长,所以在实现了内容文字的动态国际化功能后,建议去每一个页面都去进行实际的切换对比查看,对于某些文字超出限定范围的情况,需要单独的定制化的去优化(如调整样式或者翻译的文本内容),以期达到最佳效果。

提醒: 通常我们进行国际化,只需要国际化我们开发负责实现的那些固定的文字内容即可,这里有两个关键词:开发负责实现、固定内容。进一步的解释就是,系统功能面板(比如由操作系统提供的一些显示内容,不需要我们开发处理,通常会跟随操作系统的语言进行动态切换的。另外相对于固定内容,动态内容通常是由服务端返回,并且大部分内容很难在开发阶段预判,所以尽量返回内容的国际化的工作由服务端负责,或者就不需要支持动态内容的国际化。

PS: 在代码编写过程中,我使用了 var 等老式的原生js语法编写,当前市场上虽然大部分手机系统都已经支持了 ES6 的新语法,但还存在一定量的手机系统的浏览器引擎并不支持,所以如果我们进行商业应用开发的话,这一点还是要注意的。另外,本次 demo 使用的是 html 混合方式进行的页面开发,如果使用 AVM 框架进行开发,则没有这方面的问题,因为 AVM 框架本身含有 build 的编译过程,同时 AVM 框架本身就是采用的类vue语法规则,所以可以去除引入vue框架的步骤,并可以对 ES6等新语法进行兼容性处理,反而开发起来变得更加简单。

道阻且长,祝顺利!加油 -~~!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1396209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用JS逆向爬取网站数据

引言&#xff1a; JS逆向是指利用编程技术对网站上的JavaScript代码进行逆向分析&#xff0c;从而实现对网站数据的抓取和分析。这种技术在网络数据采集和分析中具有重要的应用价值&#xff0c;能够帮助程序员获取网站上的有用信息&#xff0c;并进行进一步的处理和分析。 基…

golang利用redis和gin实现保存登录状态,校验登录

保存用户登录状态&#xff0c;一般常用的方式有两种 一、生成token&#xff0c;然后token保存到数据库用户表里面&#xff0c;每次登录的时候&#xff0c;自动更新&#xff0c;容纳后每次用的时候&#xff0c;去取出来校验&#xff0c;这种方式&#xff0c;数据库压力大&#…

表的增删改查CURD(基础)

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;MySql&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 新增&#xff08;Create&#xff09; 全列插入 指定列…

GB/T28181-2022之图像抓拍规范解读和设计实现

技术背景 GB/T28181-2022相对2016版&#xff0c;对图像抓拍有了明确的界定&#xff0c;图像抓拍在视频监控行业非常重要, Android平台GB28181设备接入端&#xff0c;无需实时上传音视频实时数据的情况下&#xff0c;就可以抓图上传到指定的图像存储服务器上。 图像抓拍基本要…

Ubuntu20.04安装配置OpenCV-Python库并首次执行读图

一、选择三方提供的预编译包安装&#xff1a; 可以从官网下载 OpenCV 的安装包&#xff0c;编译后使用&#xff1b;也可以直接使用第三方提供的预编译包 安装。显然后者不需要执行编译步骤&#xff0c;更便捷。选择由 PyPI 提供的 OpenCV 安装包&#xff0c;可以在 https://py…

010-新手如何建立一个属于自己的图像处理FPGA/ZYNQ框架(自己的用着才舒服,内容非常全面!)

文章目录 前言一、图像处理框架二、图像采集输入1.常用视频流格式&#xff1a;Rgb565/Bayer1.RGB565数据流格式2.Bayer阵列数据流格式 2.图像预处理&#xff1a;时钟域同步/去马赛克/色彩空间转换/滤波1.时钟域同步2.图像去马赛克化3.色彩空间转换4.滤波 三、图像算法处理1.图像…

《世界之外》提前开测,网易打响国乙大战

1月18日&#xff0c;国乙市场迎来了一场大战。 原定于1月26日开服的网易新乙游《世界之外》&#xff0c;突然宣布在1月18日进行不删档、不限量测试&#xff0c;从某种意义上来说&#xff0c;其实就等同于提前公测。 而同一天开服的还有叠纸的全新3D乙游《恋与深空》&#xff…

【Redis】基于Token单点登录

基于Token单点登录 获取验证码 流程图 #mermaid-svg-DLGHgCofEYXVSmI5 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-DLGHgCofEYXVSmI5 .error-icon{fill:#552222;}#mermaid-svg-DLGHgCofEYXVSmI5 .error-text{f…

unocss+iconify技术在vue项目中使用20000+的图标

安装依赖 npm i unocss iconify/json配置依赖 vue.config.js文件 uno.config.js文件 main.js文件 使用 <i class"i-fa:user"></i> <i class"i-fa:key"></i>class名是 i- 开头&#xff0c;跟库名:图标名&#xff0c;那都有什么库…

Springboot+vue项目部署所有遇到的坑

https://flowus.cn/siriusx/share/0a818075-372b-4948-88af-c75c1d10ceab项目地址及笔记 Spring Boot3VUE3前后端分离项目基于Jwt的校验方案 环境搭建 安装jdk17 安装mysql server https://ubuntu.com/server/docs/databases-mysql 将服务器root账号由系统验证改为密码验证…

c语言-结构体内存对齐

文章目录 前言一、结构体内存对齐总结 前言 本篇文章介绍结构体内存对齐。 一、结构体内存对齐 定义两个结构体&#xff1a; struct S1 {char c1;int i;char c2; };struct S2 {char c1;char c2;int i; }; //输出结构体大小 int main() {printf("%u\n", sizeof(st…

提升开发效率,Fiddler Everywhere for Mac助您解决网络调试难题

在现代软件开发中&#xff0c;网络调试是一个不可或缺的环节。无论是前端开发还是后端开发&#xff0c;我们经常需要对网络请求进行监控和调试&#xff0c;以便及时发现并解决问题。而Fiddler Everywhere for Mac作为一款强大的网络调试工具&#xff0c;能够帮助开发者提升工作…

【01】mapbox js api加载arcgis切片服务

需求&#xff1a; 第三方的mapbox js api加载arcgis切片服务&#xff0c;同时叠加在天地图上&#xff0c;天地图坐标系web墨卡托。 效果图&#xff1a; 形如这种地址去加载http://zjq2022.gis.com:8080/demo/loadmapboxtdt.html 思路&#xff1a; 需要制作一个和天地图比例…

视觉检测系统:工厂生产零部件的智能检测

在工厂的生产加工过程中&#xff0c;工业视觉检测系统被广泛应用&#xff0c;并且起着重要的作用。它能够对不同的零部件进行多功能的视觉检测&#xff0c;包括尺寸和外观的缺陷。随着制造业市场竞争越来越激烈&#xff0c;对产品质检效率的要求不断提高&#xff0c;传统的人工…

EMQX安装和Java使用

一、EMQX介绍 EMQX是大规模分布式MQTT消息服务器&#xff0c;可以高效可靠连接海量物联网设备&#xff0c;实时处理分发消息与事件流数据&#xff0c;助力构建关键业务的物联网与云应用。EMQX 作为物联网应用开发和物联网平台搭建必须用到的基础设施软件&#xff0c;主要在边缘…

田园好比一幅美丽的画

一望无垠的麦田&#xff0c;清新的空气&#xff0c;茂密的小树林&#xff0c;这一切都呈现在田园里。 清晨&#xff0c;东方刚刚泛起了鱼肚白&#xff0c;一切都雾蒙蒙的&#xff0c;仿佛给大地披上了一层薄薄的轻纱&#xff0c;大地在沉睡当中&#xff0c;小花沉静在美梦中&am…

ARM64汇编01 - 环境搭建

arm官方手册 由于市面上几乎没有arm相关书籍&#xff0c;所以推荐看官方文档。虽然是英文的&#xff0c;看不下去也要硬看&#xff0c;毕竟搞这方面的还是得有啃英文文档/书籍的能力。 另外&#xff0c;再推荐一个翻译网站&#xff1a;https://www.deepl.com/zh/translator …

git报错:Failed to connect to github.com port 443: Timed out

git提交报错 git报错&#xff1a;Failed to connect to github.com port 443: Timed out解决办法 使用ping github.com 发现ping不通修改hosts文件&#xff0c;让主机跳过DNS服务器 直接根据hosts配置信息进行替换域名在ipaddress.com查询Github真实IP地址 打开hosts文件 添加…

【Java SE】基础知识回顾——【13.线程 | 同步】

【线程 同步】 第一章 Thread 1.1 Thread类 /*** author 270* 获取线程的名称&#xff1a;* 1.使用Thread中的方法getName()* String getName() 返回该线程的名称* 2.可以获取到当前正在执行的线程&#xff0c;使用线程中的方法getName()获…

【年度TikTok电商数据解析】火遍全网!出单率超高!这个产品会成为2024年卖家新宠吗?

随着大众对口腔健康越来越重视&#xff0c;消费者对漱口水、牙线、口腔清新剂等口腔卫生产品形成深度依赖。 当然&#xff0c;这一趋势对于我们TikTok爆款商机打造息息相关。 然而&#xff0c;在目前的口腔护理赛道&#xff0c;高露洁、宝洁、飞利浦等巨头盘踞&#xff0c;掌握…