当前位置: 首页 > news >正文

Android 无Bug版 多语言设计方案!

出海业务为什么要做多语言?

1.市场扩大与本地化需求:

通过支持多种语言,出海项目可以触及更广泛的国际用户群体,进而扩大其市场份额。

本地化是吸引国际用户的重要策略之一,而语言本地化是其中的核心。使用用户的母语能够提供更好的用户体验,并增加用户黏性。

2.文化敏感性和尊重:

不同的语言往往代表着不同的文化和习惯。通过提供多语言支持,出海项目能够表现出对目标市场文化的敏感性和尊重,从而建立更好的品牌形象。

3.提高用户满意度和参与度:

使用用户的母语进行交流可以消除语言障碍,使用户更容易理解和使用产品。

这有助于提高用户的满意度和参与度,进而增加用户留存和转化率。

所以,出海应用适配多语言是业务开展过程中的重中之重,建议大家App都要实现多语言功能,感受其带来的好处。  

多语言常见问题

1. Android N版本适配问题

2. 切换系统导航,更改深色模式导致多语言无法适配问题

3. 系统授权弹窗导致ApplicationContext中的Local被还原

4. 切换语言,系统通知栏显示不是当前设置的语言

5. Service服务中Toast不适配

6. 如何正确获取系统当前语言

7. WebView第一次加载多语言不适配

功能虽不太难,但遇到的问题还是比较多的,下面给大家分享我们在用的多语言方案,有问题还希望大家积极指出。

无Bug版 多语言设计方案

1.多语言方案基本原理:

实现多国语言的原理是根据用户选择的语言或者手机系统设置的语言来加载相应的语言资源文件。当用户切换语言时,应用程序会重新加载对应语言的资源文件,从而显示相应的文本内容。

2.无Bug版 多语言设计方案实践

如果您应用内内置了所有的语言文本,则只需要根据系统语言切换即可,实现方式也较为简单。如果您只兼容几种语言,要根据用户选择来切换App语言,就较为复杂一些,下面我们分别来讲一下。

(1) 跟随系统切换

通过Android Studio,(当然如果知道语言的缩写可以直接在res目录下建立不同名称的values文件例如中文values-zh),右击res->New->Android Resource File 会打开一个新的弹窗,在File name 输入框填写strings,如下图在红色圈中区域找到Local 点击>> 后就可以选择相关的国语言,点击OK会在res目录下生成一个新的values-xx目录,接下来就可以在该目录的strings.xml 添加相关语言的文案即可

图片

图片

打开手机的设置,切换系统语言(例如你项目的默认语言是中文,你上一步添加的是values-en目录,切换语言到英文),这是重新打开App,你看到App上的显示的就是英文了。

(2) App 内设置切换语言

以上2个步骤就可以简单的实现了系统切换多语言功能,但是产品为了让用户更好的使用产品,App内会有一个设置切换语言的功能,让用户自己选择App内的语言(往往我们无法支持所有的语言)。

对于这种需求我们如何设计呢?

图片

主要代码如下,文章末尾会给出github地址:

‍基类复写attachBaseContext设置上下文

abstract class BaseForLanguageActivity : Activity() {  override fun attachBaseContext(newBase: Context) {    super.attachBaseContext(LanguageUtil.wrap(newBase, LanguageUtil.getLocaleByLanguage()))}}

获取用户设置的默认语言,如果没有设置获取本地设备的默认语言(Android 7.0以及以上需要获取本地语言列表)

private fun getLanguage(): String {  val defaultLanguage = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {    Resources.getSystem().configuration.locales[0].language  } else {    Locale.getDefault().language  }    return getInstance()[KEY_LANGUAGE, defaultLanguage]}

通过第二步获取的语言来判断设置的Local类型​​​​​​​

fun getLocaleByLanguage(): Locale {  val locale = if (getLanguage().equals(LanguageType.ENGLISH.language, ignoreCase = true)) {    Locale.ENGLISH  } else if (getLanguage().equals(LanguageType.BANGLADESH.language, ignoreCase = true)) {    Locale(LanguageType.BANGLADESH.language)  } else {    Locale(LanguageType.DEFAULT.language)  }  return locale}

根据Locale(Android 7.0以及以上需要设置本地语言列表)重新包装上下文Context,在Activity的attachBaseContext方法会用到​​​​​​​

fun wrap(context: Context, newLocale: Locale): Context {
  var context = context  val res = context.resources  val configuration = res.configuration  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {    configuration.setLocale(newLocale)    val localeList = LocaleList(newLocale)    LocaleList.setDefault(localeList)    configuration.setLocales(localeList)    context = context.createConfigurationContext(configuration)  } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    configuration.setLocale(newLocale)    context = context.createConfigurationContext(configuration)  }  return ContextWrapper(context)}

保存用户设置的语言​​​​​​​

private fun setLanguage(language: String?) {  getInstance().put(KEY_LANGUAGE, language)}
fun saveChange(language: String) {  setLanguage(language)}

应用内获取string资源使用以下方法getString,确保每次获取的上下文里的Local是当前应该显示的语言​​​​​​​

object Extentions {  fun getString(@StringRes resId: Int) = getContext().getString(resId)    private fun getContext(): Context {    return LanguageUtil.getLanguageContext()  }}

LanguageContext是一个枚举类 通过这个可以获取相关语言的上下文,并获取相关语言下的资源文件​​​​​​​

enum class LanguageContext(val languageType: LanguageType) {  DEFAULT(LanguageType.DEFAULT) {    private var context: Context = LanguageUtil.wrap(Extentions.getApp(), Locale(languageType.language))        override fun getContext(): Context {                return context              }    },        ENGLISH(LanguageType.ENGLISH) {        private var context: Context = LanguageUtil.wrap(Extentions.getApp(), Locale(languageType.language))                override fun getContext(): Context {                return context              }    },        BANGLADESH(LanguageType.BANGLADESH) {        private var context: Context = LanguageUtil.wrap(Extentions.getApp(), Locale(languageType.language))                override fun getContext(): Context {                return context              }    };        abstract fun getContext(): Context        }}

讲到这里,出海项目的多语言适配就结束了,本Demo解决了开头提出的所有问题。Gitgub地址如下,欢迎大家下载体验:https://github.com/loveAndroidAndroid/OveraeaDemos  

推荐阅读

GooglePlay账号关联审查机制详解

另类封号!别让你的Google老账号为你的粗心买单

Google Play开发者组织身份验证(个人转组织)详解

相关文章:

Android 无Bug版 多语言设计方案!

出海业务为什么要做多语言? 1.市场扩大与本地化需求: 通过支持多种语言,出海项目可以触及更广泛的国际用户群体,进而扩大其市场份额。 本地化是吸引国际用户的重要策略之一,而语言本地化是其中的核心。使用用户的母语…...

Nginx02-安装

零、文章目录 Nginx02-安装 1、Nginx官网 Nginx官网地址:http://nginx.org/ 2、Nginx下载 (1)Nginx下载 下载页地址:http://nginx.org/en/download.html (2)更老版本下载 下载页地址:http…...

大模型基础架构

Transformer 设计者:Google 特点:最流行,几乎所有大模型都用它 代码:https://github.com/openai/finetune-transformer-lm/blob/master/train.py RWKV 设计者:PENG Bo 特点:可并行训练,推理性…...

MySQL 实验 10:数据查询(3)—— 聚合函数与分组查询

MySQL 实验 10:数据查询(3)—— 聚合函数与分组查询 目录 MySQL 实验 10:数据查询(3)—— 聚合函数与分组查询一、聚合函数1、计数函数(COUNT)2、求和函数(SUM&#xff0…...

感知机学习算法

感知机 一、感知机简介二、感知机模型2.1 感知机的基本组成2.2 求和函数2.2.1 时间总合2.2.2 空间总合 2.3 激活函数2.4 学习算法2.4.1 赫布学习规则2.4.2 Delta学习规则 三、 结论参考文献 一、感知机简介 M-P神经元模型因其对生物神经元激发过程的极大简化而成为神经网络研究…...

2024年双十一有什么好物推荐?双十一必买清单大汇总

随着科技的飞速发展,数码产品已成为我们生活中不可或缺的伙伴。2024年双十一购物狂欢节即将来临,众多消费者早已摩拳擦掌,准备在这个年度盛事中淘到心仪的数码好物。在这个信息爆炸的时代,如何从琳琅满目的商品中挑选出性价比高、…...

C语言贪吃蛇

#只讲逻辑不讲一些基础,基础大概过一遍就行# project-one: 无 (gitee.com)仓库里面有原代码 一、基础工作 1、先将你的编译器换成32位环境,也就是x86, 如果是控制台主机窗口则管,若不是需要改为控制台主机窗口 打开运行窗口后点…...

SpringBoot宠物咖啡馆平台:创新设计与高效实现

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理基于Spring Boot的宠物咖啡馆平台的设计与…...

李宏毅深度学习-梯度下降和Batch Normalization批量归一化

Gradient Descent梯度下降 ▽ -> 梯度gradient -> vector向量 -> 下图中的红色箭头(loss等高线的法线方向) Tip1: Tuning your learning rates Adaptive Learning Rates自适应lr 通常lr会越来越小 Adaptive Learning Rates中每个参数都给它不…...

java集合框架都有哪些

Java集合框架(Java Collections Framework)是Java提供的一套设计良好的支持对一组对象进行操作的接口和类。这些接口和类定义了如何添加、删除、遍历和搜索集合中的元素。Java集合框架主要包括以下几个部分: 接口: Collection&…...

笔记整理—linux进程部分(8)线程与进程

前面用了高级IO去实现鼠标和键盘的读取&#xff0c;也说过要用多进程方式进行该操作&#xff1a; int mian(void) {int ret-1;int fd-1;char bug[100]{0};retfork();if(0ret){//子进程&#xff0c;读鼠标}if(0<ret){//父进程&#xff0c;读键盘}else{perror("fork&quo…...

使用 Python 实现遗传算法进行无人机路径规划

目录 使用 Python 实现遗传算法进行无人机路径规划引言1. 遗传算法概述1.1 定义1.2 基本步骤1.3 遗传算法的特点 2. 使用 Python 实现遗传算法2.1 安装必要的库2.2 定义类2.2.1 无人机模型类2.2.2 遗传算法类 2.3 示例程序 3. 遗传算法的优缺点3.1 优点3.2 缺点 4. 改进方向5. …...

JAVA基础: synchronized 和 lock的区别、synchronized锁机制与升级

1 synchronized 和 lock的区别 synchronized是一个关键字&#xff0c; lock是一个接口&#xff0c;实际使用的是实现类 synchronized通过触发的是系统级别的锁机制&#xff0c; lock是API级别的锁机制 synchronized自动获得锁&#xff0c;自动释放锁。 lock需要通过方法获得锁…...

自动驾驶 车道检测实用算法

自动驾驶 | 车道检测实用算法 车道识别是自动驾驶领域的一个重要问题&#xff0c;今天介绍一个利用摄像头图像进行车道识别的实用算法。该算法利用了OpenCV库和Udacity自动驾驶汽车数据库的相关内容。 该算法包含以下步骤&#xff1a; 摄像头校准&#xff0c;以移除镜头畸变&…...

22.第二阶段x86游戏实战2-背包遍历REP指令详解

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…...

java 的三种IO模型(BIO、NIO、AIO)

java 的三种IO模型&#xff08;BIO、NIO、AIO&#xff09; 一、BIO 阻塞式 IO&#xff08;Blocking IO&#xff09;1.1、BIO 工作机制1.2、BIO 实现单发单收1.3、BIO 实现多发多收1.4、BIO 实现客户端服务端多对一1.5、BIO 模式下的端口转发思想 二、NIO 同步非阻塞式 IO&#…...

低级语言和高级语言、大小写敏感、静态语言和动态语言、链接

低级语言和高级语言 一般而言&#xff0c;更接近硬件的语言被称为低级语言&#xff0c;反之&#xff0c;更远离硬件被称为高级语言。C语言既有低级语言的特点&#xff0c;又有高级语言的特点&#xff0c;又被称为系统语言。Java/Python一般被称为高级语言。 大小写敏感 DOS/Win…...

P3197 [HNOI2008] 越狱

题目传送门 题面 [HNOI2008] 越狱 题目描述 监狱有 n n n 个房间&#xff0c;每个房间关押一个犯人&#xff0c;有 m m m 种宗教&#xff0c;每个犯人会信仰其中一种。如果相邻房间的犯人的宗教相同&#xff0c;就可能发生越狱&#xff0c;求有多少种状态可能发生越狱。 …...

会声会影导出视频mp4格式哪个最高清,会声会影输出格式哪个清晰

调高分辨率后&#xff0c;mp4视频还是不清晰。哪怕全部使用4K级素材&#xff0c;仍然剪不出理想中的高画质作品。不是你的操作有问题&#xff0c;而是剪辑软件没选对。Corel公司拥有全球顶尖的图像处理技术&#xff0c;该公司研发的会声会影视频剪辑软件&#xff0c;在过去的20…...

Linux:进程调度算法和进程地址空间

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 进程调度算法 1.1 进程队列数据结构 1.2 优先级 ​编辑 1.3 活动队列 ​编辑 1.4 过期队列 1.5 active指针和expired指针 1.6 进程连接 二 进程地址空间 2.1 …...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...