实战技巧:为Android应用设置独立的多语言

原文链接 实战技巧:为Android应用设置独立的多语言

通常情况下多语言的设置都在系统设置中,应用需要做的就是提供本应用所使用的字串的多语言翻译,使用时使用R.string.app_name类似的引用,然后系统会根据用户在系统设置中的选项来选择合适的具体的语言。并且这是一个全局选项,也就是说选择一个多语言后整个手机都变了。但有些时候,应用想要自己能够设置一个独自的多语言,也就是说想要给自己的应用设置一个不同于全局的多语言。今天就来研究一下这个话题。

这样做的目的是为了提供更好的用户体验,因为一些仅支持某些特定语言的应用,可能会与系统全局选项冲突,或者只在某些固定地区发行的应用,单独的个性化的局部设置会更好一些。这个谷歌已经通过Jetpack中的appcomat库给与了比较好的支持,详细的可以参考这个文档,以及官方的Sample。我们在官方文档基础之上再叠加试验和理解,做进一步的总结。

主要分为两种方法,一是系统支持单独给应用设置多语言;二是应用中独自设置,这个也是更为通用的解法。

注意:这里的方法都是让某一个应用内部使用的多语言改变为相应的设置(一般情况下是与系统全局设置不一样的),但是需要注意仅仅局限于应用启动后的应用内部界面使用的语言。对于像桌面上应用的入口仍是系统全局设置为准,因为这个入口并不属于应用自己管辖范围内的。

系统设置中支持为应用设置单独多语言

谷歌官方的表述是从Android 13(Android T, SDK 33)开始,就支持了在系统中有一个入口,可以为每个应用单独设置多语言选项。这一部分里面描述的方法也都是支持这个系统入口的情况才能生效的。需要注意,虽然谷歌官方说从Android 13开始就支持了,但这个也要取决 于厂商的定制,目前看大部分国内厂商会把这个功能和入口给屏蔽掉,那么这里后面描述的方法也就都不会生效了。

入口在哪里

需要通过系统设置来进行,有两个入口:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • Settings(设置)> Additional Settings (更多设置) > Languages & Input (语言和输入) > (App Languages) 应用语言 > select an app(选择一个应用)
  • Settings(设置)> Apps (应用)> select an app(选择一个应用) > Language(语言)

具体的方法,又分为两种,一是自动式的,二是手动式的。

自动添加

说是自动,其实也是利用IDE(即Android Studio)和编译打包时自动根据res下面的多语言生成一份配置而已。在build.gradle或者build.gradle.kts中的android下面添加generateLocaleConfig = true:

	android {
		androidResources {
			generateLocaleConfig = true
		}
	}

然后在resl中增加一个名为resources.properties的文件,加入默认值配置:

unqualifiedResLocale=en-US

手动添加

在res/xml中增加文件locales_config.xml,加入需要支持的多语言选项,如:

<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
   <locale android:name="en-US"/>
   <locale android:name="en-GB"/>
   <locale android:name="fr"/>
   <locale android:name="ja"/>
   <locale android:name="zh-Hans-MO"/>
   <locale android:name="zh-Hant-MO"/>
</locale-config>

然后在AndroidManifest.xml中的appllication加上这一个属性:

<manifest>
	...
	<application
		...
		android:localeConfig="@xml/locales_config">
	</application>
</manifest>

因为还没有找到支持如此设置的手机,所以上述方法未经验证。

在应用内部设置多语言

这个是更为通用的做法,具体的UI就是可以随便弄了,弄个List或者DrowDownMenu都可以。重点是让设置生效的时候需要用到一个API,叫做setApplicationLocales()和getApplicationLocales()。并且在appcompat 1.6.0以后的版本,有比较方便的API可以直接使用。

val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)

如果要还原使用系统设置中的全局多语言配置,可以用LocaleListCompat.getEmptyLocaleList()当作参数。

特别注意:此方法要想生效,宿主Activity必须是继承自appcompat中的AppCompatActivity,而不是其他 。

为了兼容以前的版本(Android 12,API level 32以前),还需要在AndroidManifest中添加一个额外的Service:

<application
  ...
  <service
    android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
    android:enabled="false"
    android:exported="false">
    <meta-data
      android:name="autoStoreLocales"
      android:value="true" />
  </service>
  ...
</application>

需要注意,这个Service在appcomat库中已经定义好了,只需要在manfiest里添加一下就可以了。

另外需要注意的是,一般情况下,应用自己肯定 会保存一下当前用户所选择的语言。但如果系统也支持应用语言选择入口的话,那么通过系统入口也是可能会修改应用的多语文选项的,这时,就需要把系统的选项与应用内部的选项进行同步。可以通过AppCompatDelegate.getApplicationLocales来获取当前生效的语言选项,它是由appcompat库来维护的,肯定是最新的,所以应用自己保存的选项如果与这个API的结果不一致,就要重置为这个API的结果。

参考资料

  • Per-app language preferences
  • user-interface-samples/PerAppLanguages

原创不易,打赏点赞在看收藏分享 总要有一个吧

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不瞒各位,不安装软件也能操作Xmind文档

大家好&#xff0c;我是小悟 作为搞技术的一个人群&#xff0c;时不时就要接收产品经理发过来的思维脑图&#xff0c;而此类文档往往是以Xmind编写的&#xff0c;如果你的电脑里面没有安装Xmind的话&#xff0c;不好意思&#xff0c;是打不开这类后缀结尾的文档。 打不开的话…

【雷电模拟器桥接问题解决方法】

1.ROOT权限开启 2.开启网络桥接模式&#xff0c;选择静态IP设置&#xff0c;点击安装桥接网卡&#xff0c;填写IP地址&#xff08;注意&#xff1a;IP地址要与host主机在同一IP段内&#xff09; 3.重启后 adb shell就能进入到模拟器控制台中了&#xff0c;如果出现以下内容&…

进程程序替换和shell实现

先前fork说创建子进程执行代码&#xff0c;如何让子进程执行和父进程完全不一样的代码?程序替换。 一 单进程替换演示 1 execl函数使用 最近转到在vs code下写代码&#xff0c;之前也在xhell下用过execl函数&#xff0c;所以才想写篇博客总结总结&#xff0c;没想到在vs code…

(C语言)计算n的阶乘

要求使用双精度 #include<stdio.h> double factorial(int n) {if(n 1)return 1;return n * factorial(n-1); } int main() {int n ;double res;scanf("%d",&n);res factorial(n);printf("%lf",res); return 0; } 运行截图&#xff1a; 注&am…

oops-framework框架 之 界面管理(三)

引擎&#xff1a; CocosCreator 3.8.0 环境&#xff1a; Mac Gitee: oops-game-kit 注&#xff1a; 作者dgflash的oops-framework框架QQ群&#xff1a; 628575875 回顾 在上文中主要通过oops-game-kit大家了一个新的模版项目&#xff0c; 主要注意项是resources目录下的两个文…

Python Opencv实践 - Yolov3目标检测

本文使用CPU来做运算&#xff0c;未使用GPU。练习项目&#xff0c;参考了网上部分资料。 如果要用TensorFlow做检测&#xff0c;可以参考这里 使用GPU运行基于pytorch的yolov3代码的准备工作_little han的博客-CSDN博客文章浏览阅读943次。记录一下自己刚拿到带独显的电脑&a…

卷积神经网络(CNN):艺术作品识别

文章目录 一、前言一、设置GPU二、导入数据1. 导入数据2. 检查数据3. 配置数据集4. 数据可视化 三、构建模型四、编译五、训练模型六、评估模型1. Accuracy与Loss图2. 混淆矩阵3. 各项指标评估 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&#xf…

继承 多态 拆箱装箱 128陷阱 枚举类

继承 在java里一个类只能继承一个类&#xff0c;但可以被多个类继承&#xff1b;c里一个类可以继承多个类&#xff1b; 子类可以使用父类的方法&#xff1b; 在java中&#xff0c;Object是所有类的父类&#xff1b; equals方法比较的是对象是否指向同一个地方&#xff0c;这个方…

原生横向滚动条 吸附 页面底部

效果图 /** 横向滚动条 吸附 页面底部 */ export class StickyHorizontalScrollBar {constructor(options {}) {const { el, style } optionsthis.createScrollbar(style)this.insertScrollbar(el)this.setScrollbarSize()this.onEvent()}/** 创建滚轴组件元素 */createS…

Windows下打包C++程序无法执行:无法定位程序输入点于动态链接库

1、问题描述 环境&#xff1a;CLionCMakeMinGW64遇到问题&#xff1a;打包的exe无法运行&#xff0c;提示无法定位程序输入点于动态链接库。 2、解决思路 ​ 通过注释头文件的方式&#xff0c;初步定位问题是因为使用了#include <thread> 多线程库引起的。而且exe文件…

外包干了2个月,技术倒退2年。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入深圳某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

如何创建maven项目的多模块项目

Maven多模块项目是指一个Maven项目中包含多个子模块&#xff0c;每个子模块又是一个独立的Maven项目&#xff0c;但它们之间可以存在依赖关系。Maven多模块项目可以方便地管理多个子模块的依赖和构建过程&#xff0c;同时也可以提高项目的可维护性和可扩展性。创建maven项目的父…

ChatGPT发布一年后,搜索引擎的日子还好吗?

导读&#xff1a;生成式AI&#xff0c;搜索引擎的终结者还是进化加速器 ChatGPT发布刚刚一年&#xff0c;互联网世界已经换了人间。 2023年&#xff0c;以ChatGPT和大模型为代表的生成式AI浪潮对全球互联网、云计算、人工智能领域都带来巨大冲击。而且生成式AI在各行各业的应用…

深入理解JVM虚拟机第二十七篇:详解JVM当中InvokeDynamic字节码指令,Java是动态类型语言么?

😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783824 📚📚 工作微信:BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Sp…

[ROS2] --- ROS diff ROS2

1 ROS存在的问题 一旦Ros Master主节点挂掉后&#xff0c;就会造成整个系统通信的异常,通信基于TCP实现&#xff0c;实时性差、系统开销大对Python3支持不友好&#xff0c;需要重新编译消息机制不兼容没有加密机制、安全性不高 2 ROS and ROS2架构对比 ROS和ROS2架构如下图所…

Redis实战篇笔记(最终篇)

Redis实战篇笔记&#xff08;七&#xff09; 文章目录 Redis实战篇笔记&#xff08;七&#xff09;前言达人探店发布和查看探店笔记点赞点赞排行榜 好友关注关注和取关共同关注关注推送关注推荐的实现 总结 前言 本系列文章是Redis实战篇笔记的最后一篇&#xff0c;那么到这里…

如何使用cpolar内网穿透工具实现公网SSH远程访问Deepin

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

卷积神经网络(CNN):乳腺癌识别.ipynb

文章目录 一、前言一、设置GPU二、导入数据1. 导入数据2. 检查数据3. 配置数据集4. 数据可视化 三、构建模型四、编译五、训练模型六、评估模型1. Accuracy与Loss图2. 混淆矩阵3. 各项指标评估 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&#xf…

(C语言)交换变量

在主函数中定义两个双精度变量x,y&#xff0c;并输入值&#xff0c;编写一个函数实现交换变量x,y&#xff0c;要求函数的参数是指针类型&#xff0c;并编写一个主函数进行调用。 #include<stdio.h> void swap(double *x,double *y) {double t;t *x;*x *y;*y t;} int …

Web前端 ---- 【vue】vue 组件传值(props、全局事件总线、消息的订阅与发布)

目录 前言 父子组件 父传子 子传父 全局事件总线 什么叫全局事件总线 如何创建全局事件总线 如何在组件上获取到这个全局vc对象 最常用的创建全局事件总线 兄弟组件 消息订阅与发布 安装 使用 爷孙组件 前言 在上篇文章我们介绍了父子组件之间的传值通信&#xff…