これは私を助けてくれた答えの続きです この投稿
build.gradle
から次のように文字列リソースを追加できます。
productFlavors { main{ resValue "string", "app_name", "InTouch Messenger" } googlePlay{ resValue "string", "app_name", "InTouch Messenger: GPE Edition" } }
それは魅力のように機能し、フレーバーごとに異なるアプリ名を持つという目的を果たします。 (元のapp_name
文字列リソースがstrings.xml
ファイルから削除されています。
しかし、build.gradle
から追加されたこの文字列リソースにローカライズされた文字列を追加するにはどうすればよいですか?
ロケールを指定して渡すことができる追加のパラメーターはありますか? [〜#〜]または[〜#〜]gradle
タスクを使用してそれを行うことは可能ですか?
注:strings.xml
を使用してこれを行うことはできません(プロジェクトの構造がいくつかあるため、実行できません)
ただし、生成されたリソースに関する他の回答は、ユースケースにとってはやり過ぎかもしれません。私があなたのプロジェクトについて現在知っていることを基にして、これがより適していると思います:(これを生成されたリソースと組み合わせることができるというわけではありません)
src/flavor1/res/values/strings.xml
<string name="app_name_base">InTouch Messenger"</string>
<string name="app_name_gpe">InTouch Messenger: GPE Edition"</string>
src/flavor1/res/values-hu/strings.xml
<string name="app_name_base">InTouch Üzenetküldő"</string>
<string name="app_name_gpe">InTouch Üzenetküldő: GPE Változat"</string>
src/flavor2/res/values/strings.xml
<string name="app_name_base">Whatever Messenger"</string>
<string name="app_name_gpe">Whatever Messenger: GPE Edition"</string>
src/flavor2/res/values-hu/strings.xml`
<string name="app_name_base">Whatever Üzenetküldő"</string>
<string name="app_name_gpe">Whatever Üzenetküldő: GPE Változat"</string>
build.gradle
Android {
sourceSets {
[flavor1, flavor3].each {
it.res.srcDirs = ['src/flavor1/res']
}
[flavor2, flavor4].each {
it.res.srcDirs = ['src/flavor2/res']
}
}
productFlavors { // notice the different numbers than sourceSets
[flavor1, flavor2].each {
it.resValue "string", "app_name", "@string/app_name_base"
}
[flavor3, flavor4].each {
it.resValue "string", "app_name", "@string/app_name_gpe"
}
}
}
この意味は flavor1/2
余分な未使用のapp_name_gpe
文字列リソースですが、それはaaptによって処理されます:
Android {
buildTypes {
release {
shrinkResources true // http://tools.Android.com/tech-docs/new-build-system/resource-shrinking
}
これらの文字列を操作する必要がない場合は、strings.xml
に移動するのが最善のオプションですが、これにより、フレーバー間ですべてのres
フォルダーを共有できます。 build.gradle
のプロパティに基づいてこれらの文字列を生成する場合、残念ながら運が悪いと思います。
編集:私が何を意味するのかを明確にする上記の操作といくつかのオプションの追加:
これらの文字列を操作するとはビルドパラメータ、コマンドラインからの読み取り、またはビルドプロセス中の環境変数とのある種の連結を意味します(例:後でバグを追跡しやすくするためにSHA1をコミットします)。操作が不要な場合は、strings.xml
を選択できます。ただし、フレーバーのres
フォルダーを上書きすると、すべてが上書きされるため、限られた数の文字列を除いて、複数のフレーバーが同じres
を共有する場合に問題が発生する可能性があります。
各APKに独自のロケールがある場合、それはフレーバーのresValue
またはbuildConfigField
にすぎません。変数をに定義して、値を簡単に再利用できます。何かのようなもの
def myVar = "var"
...
flavor1 {
resValue "string", "my_res_string", "${myVar}"
}
flavor2 {
resValue "string", "my_res_string", "${myVar}"
}
ただし、同じAPKで複数のロケールが必要であり、実行時にAndroidによって選択される場合、文字列は正しいvalues-<locale>
フォルダーにある必要があります。
ここではさまざまなレベルで操作しています。BuildConfig
はコードであり、ローカライズされていないため、ハードコードされた文字列に対してLint警告が表示されます。 Androidは<string
リソースを介して行われます。ユーザー設定に応じて実行時にシステムに言語を選択させたい場合は、それを回避する方法はありません。リソースを取得する方法はたくさんあります。ただし、values
フォルダー、build.gradleのresValue
、および生成されたリソース。
GradleのbuildSrc
プロジェクト を調べる必要があります。たとえば、src/main/values/stuff.xml
からSQL挿入を生成するために使用します。まず、いくつかのコードを示します。
buildSrc/build.gradle
// To enable developing buildSrc in IDEA import buildSrc/build.gradle as a separate project
// Create a settings.gradle in buildSrc as well to prevent importing as subproject
apply plugin: 'groovy'
repositories { jcenter() }
dependencies {
compile localGroovy()
compile gradleApi()
testCompile 'junit:junit:4.12'
}
buildSrc/src/main/groovy/Plugin.groovy
import org.gradle.api.*
/**
* Use it as
* <code>
* apply plugin: MyPlugin
* myEntities {
* categories {
* input = file(path to Android res xml with Strings)
* output = file(path to asset SQL file)
* conversion = "structure|SQL"
* }
* }
* </code>
*/
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
def entities = project.container(MyEntity)
// this gives the name for the block in build.gradle
project.extensions.myEntities = entities
def allTasks = project.task('generateYourStuff')
def allTasksClean = project.task('cleanGenerateYourStuff')
project.afterEvaluate {
entities.all { entity ->
//println "Creating task for ${entity.name} (${entity.input} --${entity.conversion}--> ${entity.output})"
def task = project.task(type: GenerateTask, "generateYourStuff${entity.name.capitalize()}") {
input = entity.input
output = entity.output
conversion = entity.conversion
}
allTasks.dependsOn task
// clean task is automagically generated for every task that has output
allTasksClean.dependsOn "clean${task.name.capitalize()}"
}
}
}
}
class MyEntity {
def input
def output
String conversion
final String name
MyEntity(String name) {
this.name = name
}
}
buildSrc/src/main/groovy/GenerateTask.groovy
import net.twisterrob.inventory.database.*
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.*
class GenerateTask extends DefaultTask {
@InputFile File input
@OutputFile File output
@Optional @Input String conversion
@TaskAction void generate() {
input.withReader { reader ->
// you may need to treat output as a folder
output.parentFile.mkdirs()
output.withWriter { writer ->
// custom transformation here read from reader, write to writer
}
}
}
}
これは、ワイルドになってここから何でもできるスケルトンです。ネットワークを介してCSVを取得し、その内容を生成されたvariant*/res/values-*/gen.xml
ファイルに拡散します。
必要に応じて手動で実行するか、ビルドライフサイクルの適切な時点で実行できます(build.gradle
内)。
Android.applicationVariants.all { com.Android.build.gradle.api.ApplicationVariant variant ->
variant.mergeAssets.dependsOn tasks.generateYourStuff
}