谷歌应用翻译问题
谷歌应用中出现的翻译需求通常无法通过修改源码的方式进行,不过可以通过overlay的方式解决,现就本人在实际工作中遇到的问题举例进行讲解。
需求是对Settings中的Android System Intelligence
这个字符串进行翻译。
- 定位系统中这个APK文件位置。
系统中可能一次放很多个APK以适应不同的平台,所以通过查看同目录中的Android.mk来确定。
###############################################################################
# ASI
LOCAL_PATH := $(my-dir)
my_archs := arm64 x86 x86_64
my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
include $(CLEAR_VARS)
LOCAL_MODULE := AndroidSystemIntelligence_Features
LOCAL_MODULE_OWNER := google
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRODUCT_MODULE := true
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk
LOCAL_OVERRIDES_PACKAGES := AndroidSystemIntelligence_Infrastructure
LOCAL_OPTIONAL_USES_LIBRARIES := androidx.window.extensions androidx.window.sidecar
LOCAL_REQUIRED_MODULES := sysconfig_asi_features PrivateComputeServices
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := AndroidSystemIntelligence_Infrastructure
LOCAL_MODULE_OWNER := google
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRODUCT_MODULE := true
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk
LOCAL_OPTIONAL_USES_LIBRARIES := androidx.window.extensions androidx.window.sidecar
LOCAL_REQUIRED_MODULES := sysconfig_asi_infrastructure PrivateComputeServices
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := PrivateComputeServices
LOCAL_MODULE_OWNER := google
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRODUCT_MODULE := true
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk
LOCAL_OPTIONAL_USES_LIBRARIES :=
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
可以看见有两个LOCAL_MODULE以AndroidSystemIntelligence
开头,且第一个有这么一段LOCAL_OVERRIDES_PACKAGES := AndroidSystemIntelligence_Infrastructure
而LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk
定义了APK的名字。
所以APK应该是以AndroidSystemIntelligence_Features开头的。结合自己的架构,可以确定APK名称为AndroidSystemIntelligence_Features_arm64.apk。
- 反编译apk以获取package name和string name
这里通过apktool这个工具来进行反编译。iBotPeaches/Apktool: A tool for reverse engineering Android apk files (github.com)
下载apktool,改名为apktool.jar,复制出AndroidSystemIntelligence_Features_arm64.apk,将两个文件放置同一目录中,建议不要带中文路径。
打开命令提示符,切换到该目录,执行java -jar apktool.jar d AndroidSystemIntelligence_Features_arm64.apk
执行完后就出现了一个同名的文件夹。
进入目录,主要关注AndroidManifest.xml文件和res中的valuse/strings.xml,因为要获取package名和string名。
打开AndroidManifest.xml文件,搜索package,找到类似这种。
打开values下的string.xml文件,找到需要翻译的字符串。
需求是要翻译Android System Intelligence这个字符串,发现有两个name,一个叫app_name,一个叫asi_settings_activity_title,不想区别,就一起翻译了吧。
- 构建overlay
在vendor目录中新建一个文件夹,本人取名为AndroidSystemIntelligenceOverlay
在里面新建一个res文件夹、Android.mk和AndroidManifest.xml文件
res文件夹里面又分别新建values文件夹和values-zh-rCN两个文件夹里面都放入string.xml文件。
先看AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.as.overlay">
<overlay
android:isStatic="true"
android:priority="1"
android:targetPackage="com.google.android.as" />
</manifest>
类似这种结构,其中android:targetPackage
后应该填写反编译出的package name,package
后面应该填一个自己定义的名字,推荐就是package name加一个.overlay。
再看Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/overlay
#include files in src directory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PROPRIETARY_MODULE := true
#include files in res diretory
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_SDK_VERSION = current
LOCAL_CERTIFICATE := platform
LOCAL_AAPT_FLAGS += --auto-add-overlay
#the name of target apk
LOCAL_PACKAGE_NAME := AndroidSystemIntelligenceOverlay
include $(BUILD_PACKAGE)
类似这种。
最后就是在string.xml中翻译字符串了。
values/strings.xml文件中加入需要翻译的字符串
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Android System Intelligence</string>
<string name="asi_settings_activity_title">Android System Intelligence</string>
</resources>
values-zh-rCN/strings.xml文件中将其翻译成对应的字符串即可。
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Android系统智能</string>
<string name="asi_settings_activity_title">Android系统智能</string>
</resources>
最后,需要在device目录中对应项目的var.mk文件中加入PRODUCT_PACKAGES,使其能编译进系统。
+=后面的是Android.mk文件中定义的LOCAL_PACKAGE_NAME
LOCAL_PACKAGE_NAME := AndroidSystemIntelligenceOverlay
。
最后编译,切换为中文语言即可看见效果。
如果这样不生效,请将Android.mk中的include $(BUILD_PACKAGE)
改成include $(BUILD_RRO_PACKAGE)