当前位置: 首页 > 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 …...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...