将 strings.xml 中的单词替换为 gradle 以获得 buildType
Replace word in strings.xml with gradle for a buildType
我有一个有多个本地化版本的项目。
现在我必须为不同的 buildTypes 替换所有 strings.xml
文件中的某个词。例如,假设我有这个:
<string>My name is Bill</string>
<string>Bill is on duty today</string>
在另一个 buildType 中我需要
<string>My name is Will</string>
<string>Will is on duty today</string>
我该怎么做(可能通过 Gradle)?
您可以执行类似 build.gradle 中的操作,但仅适用于该特定字符串资源。
resValue "string", "<string_name>", string_value
在您的应用程序(模块,而非项目)的 build.gradle 目录中创建文件 gradle.properties。在这个应用程序中放置字符串
GOOGLE_MAPS_API_KEY = ishufhiaushdiasdh
在 buildTypes 部分的 build.gradle 文件中添加字段 'buildConfigField'。它看起来像:
buildTypes {
debug {
buildConfigField "String", "GOOGLE_MAPS_API_KEY", String.format("\"%s\"", GOOGLE_MAPS_API_KEY)
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
buildConfigField "String", "GOOGLE_MAPS_API_KEY", String.format("\"%s\"", GOOGLE_MAPS_API_KEY)
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
编译项目后,您会在 BuildConfig 中发现生成的值为静态字符串 class。
为什么不直接使用动态字符串格式:
<string name="my_message">%1$s is on duty today</string>
在一个构建变体中:
<string name="name">Bill</string>
在另一个构建变体中:
<string name="name">Will</string>
在您的代码中:
String text = String.format(getResources().getString(R.string.my_message), getResources().getString(R.string.name));
好的,找到了正确的解决方案,这不是解决方法:
对于所需的 buildType
添加以下内容
applicationVariants.all { variant ->
variant.mergeResources.doLast {
def dir = new File("${buildDir}/intermediates/res/merged/${variant.dirName}") //iterating through resources, prepared for including to APK (merged resources)
println("Resources dir " + dir)
dir.eachFileRecurse { file ->
if(file.name.endsWith(".xml")) { //processing only files, which names and with .xml
String content = file.getText('UTF-8')
if(content != null && content.contains("Bill")) {
println("Replacing name in " + file)
content = content.replace("Bill", "Will") //replacing all Bill words with Will word in files
file.write(content, 'UTF-8')
}
}
}
}
一种解决方案,虽然并非适用于所有情况,但使用带有 filter
指令的 Copy
任务:
task replace (type: Copy) {
from "sources" {
include "srcStrings.xml"
filter { line -> line.replaceAll("Will", "Bill") }
}
into "strings.xml"
}
此处的答案不再适用于最新的 android 构建工具,但这里有一个适合我的新版本。
android.applicationVariants.all { variant ->
variant.mergeResources.doFirst {
variant.sourceSets.each { sourceSet ->
sourceSet.res.srcDirs = sourceSet.res.srcDirs.collect { dir ->
def relDir = relativePath(dir)
copy {
from(dir)
include '**/*.xml'
filteringCharset = 'UTF-8'
filter {
line -> line
.replace('Bill', 'Will')
}
into("${buildDir}/tmp/${variant.dirName}/${relDir}")
}
copy {
from(dir)
exclude '**/*.xml'
into("${buildDir}/tmp/${variant.dirName}/${relDir}")
}
return "${buildDir}/tmp/${variant.dirName}/${relDir}"
}
}
}
}
在处理线条时,您应该观察使用 replace()
和 replaceAll()
获得的结果。并考虑到要处理的文件的绝对目录存在(不一定在res.srcDirs)
sourceSets {
flavor {
println res.srcDirs
task testA() {
def relativeDirFile = 'src/flavor/res'
def file = "${relativeDirFile}/values/strings.xml"
def absoluteDirFile = "${rootDir}/module/${file}"
def buildDirToCopy = "${buildDir}/tmp/${relativeDirFile}/values"
copy {
from(absoluteDirFile)
filter {
String line ->
println line
line.replace("(.*)", line) // To keep the line
// OR
line.replaceAll("(.*)", "") // To erase the line
}
into(buildDirToCopy)
}
res.srcDirs += (buildDirToCopy + "/strings.xml")
// Check the directories that were included in the flavor.
println res.srcDirs
}
}
}
您终于可以 extract the task 进入另一个 gradle 文件
我也推荐深化使用regex。
GL
我有一个有多个本地化版本的项目。
现在我必须为不同的 buildTypes 替换所有 strings.xml
文件中的某个词。例如,假设我有这个:
<string>My name is Bill</string>
<string>Bill is on duty today</string>
在另一个 buildType 中我需要
<string>My name is Will</string>
<string>Will is on duty today</string>
我该怎么做(可能通过 Gradle)?
您可以执行类似 build.gradle 中的操作,但仅适用于该特定字符串资源。
resValue "string", "<string_name>", string_value
在您的应用程序(模块,而非项目)的 build.gradle 目录中创建文件 gradle.properties。在这个应用程序中放置字符串 GOOGLE_MAPS_API_KEY = ishufhiaushdiasdh
在 buildTypes 部分的 build.gradle 文件中添加字段 'buildConfigField'。它看起来像:
buildTypes {
debug {
buildConfigField "String", "GOOGLE_MAPS_API_KEY", String.format("\"%s\"", GOOGLE_MAPS_API_KEY)
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
buildConfigField "String", "GOOGLE_MAPS_API_KEY", String.format("\"%s\"", GOOGLE_MAPS_API_KEY)
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
编译项目后,您会在 BuildConfig 中发现生成的值为静态字符串 class。
为什么不直接使用动态字符串格式:
<string name="my_message">%1$s is on duty today</string>
在一个构建变体中:
<string name="name">Bill</string>
在另一个构建变体中:
<string name="name">Will</string>
在您的代码中:
String text = String.format(getResources().getString(R.string.my_message), getResources().getString(R.string.name));
好的,找到了正确的解决方案,这不是解决方法:
对于所需的 buildType
添加以下内容
applicationVariants.all { variant ->
variant.mergeResources.doLast {
def dir = new File("${buildDir}/intermediates/res/merged/${variant.dirName}") //iterating through resources, prepared for including to APK (merged resources)
println("Resources dir " + dir)
dir.eachFileRecurse { file ->
if(file.name.endsWith(".xml")) { //processing only files, which names and with .xml
String content = file.getText('UTF-8')
if(content != null && content.contains("Bill")) {
println("Replacing name in " + file)
content = content.replace("Bill", "Will") //replacing all Bill words with Will word in files
file.write(content, 'UTF-8')
}
}
}
}
一种解决方案,虽然并非适用于所有情况,但使用带有 filter
指令的 Copy
任务:
task replace (type: Copy) {
from "sources" {
include "srcStrings.xml"
filter { line -> line.replaceAll("Will", "Bill") }
}
into "strings.xml"
}
此处的答案不再适用于最新的 android 构建工具,但这里有一个适合我的新版本。
android.applicationVariants.all { variant ->
variant.mergeResources.doFirst {
variant.sourceSets.each { sourceSet ->
sourceSet.res.srcDirs = sourceSet.res.srcDirs.collect { dir ->
def relDir = relativePath(dir)
copy {
from(dir)
include '**/*.xml'
filteringCharset = 'UTF-8'
filter {
line -> line
.replace('Bill', 'Will')
}
into("${buildDir}/tmp/${variant.dirName}/${relDir}")
}
copy {
from(dir)
exclude '**/*.xml'
into("${buildDir}/tmp/${variant.dirName}/${relDir}")
}
return "${buildDir}/tmp/${variant.dirName}/${relDir}"
}
}
}
}
在处理线条时,您应该观察使用 replace()
和 replaceAll()
获得的结果。并考虑到要处理的文件的绝对目录存在(不一定在res.srcDirs)
sourceSets {
flavor {
println res.srcDirs
task testA() {
def relativeDirFile = 'src/flavor/res'
def file = "${relativeDirFile}/values/strings.xml"
def absoluteDirFile = "${rootDir}/module/${file}"
def buildDirToCopy = "${buildDir}/tmp/${relativeDirFile}/values"
copy {
from(absoluteDirFile)
filter {
String line ->
println line
line.replace("(.*)", line) // To keep the line
// OR
line.replaceAll("(.*)", "") // To erase the line
}
into(buildDirToCopy)
}
res.srcDirs += (buildDirToCopy + "/strings.xml")
// Check the directories that were included in the flavor.
println res.srcDirs
}
}
}
您终于可以 extract the task 进入另一个 gradle 文件
我也推荐深化使用regex。
GL