12

Dies zu einer Antwort in der Fortsetzung, die mir geholfen, auf this postLokalisieren von String-Ressourcen über build.gradle mit „resValue“ hinzugefügt

Wir können die Zeichenfolge-Ressource hinzufügen, wie folgt aus build.gradle:

productFlavors { 
    main{ 
     resValue "string", "app_name", "InTouch Messenger" 
    } 

    googlePlay{ 
     resValue "string", "app_name", "InTouch Messenger: GPE Edition" 
    } 
} 

Es funktioniert wie ein Zauber und dient dem Zweck, verschiedene App-Namen pro Geschmack zu haben. (Mit der ursprünglichen app_name String-Ressource aus strings.xml Datei gelöscht.

Aber wie fügen wir lokalisieren Strings für diese Zeichenfolge-Ressource von build.gradle hinzugefügt?

Gibt es einen zusätzlichen Parameter wir das Gebietsschema, passieren können? OR möglich, es zu tun, um eine gradle Aufgabe mit

Hinweis: ich kann dies mit strings.xml nicht tun (nicht machbar, weil mehrere Möglichkeiten, in denen mein Projekt ist strukturiert)

+2

Ich denke, dass, wenn Sie es lokalisieren müssen, dann wahrscheinlich nicht sein sollte die Großzahl. Der hauptsächliche Verwendungszweck besteht darin, beispielsweise zwei verschiedene API-Schlüssel zu haben, einen für Prod, einen für Dev. – hmartinezd

+0

in meinem Fall sind die Produktaromen nicht für Umgebungen, sondern für unterschiedliche Variation der App. die alle in die Produktion gehen. Meine Umgebungen werden über Build-Typ gesteuert. Kann nicht mit separaten Xml für jeden Geschmack gehen, weil ich eine Menge von ihnen habe und immer mehr. Daher wählte ich es über Gradle zu tun. – AndroidMechanic

+0

Entschuldigung dafür, dass ich 'strings.xml' Lösungen gebe, aber ich glaube nicht, dass Sie es anders machen können. Wenn Sie Probleme mit der Trennung haben, können Sie verschiedene 'res.srcDir's hinzufügen, die Sie lokalisieren, aber der hinzugefügte Ordner kann mehrere' values- /strings.xml' Dateien enthalten. – TWiStErRob

Antwort

3

Wenn Sie nicht mit diesen Strings arbeiten müssen, ist die beste Option, um strings.xml verschieben, aber das würde Sie alle res Ordner zwischen Aromen teilen. Wenn Sie diese Zeichenfolgen basierend auf einer Eigenschaft auf build.gradle generieren, dann denke ich, dass Sie leider kein Glück haben.

EDIT:klären, was ich damit meineoben arbeiten und fügen Sie einige Optionen:

von auf diesen Saiten Betrieb Ich meine eine Art Verkettung mit einem Build-Parametern, eine Lesung von Befehl während des Build-Prozesses eine Zeilen- oder Umgebungsvariable (z. B. um den Commit SHA1 zu erhalten, so dass es später einfacher ist, Fehler zu verfolgen). Wenn keine Operation erforderlich ist, kann strings.xml eine Option sein. Aber wenn Sie einen Ordner res für Geschmack überschreiben, wird alles davon überschrieben und das könnte ein Problem darstellen, wenn mehrere Aromen res mit Ausnahme einer begrenzten Anzahl von Zeichenfolgen teilen.

Wenn jedes APK sein eigenes Gebietsschema hat, dann ist es nur ein resValue oder buildConfigField in einem Geschmack. Sie können Variablen definieren, um die Wiederverwendung von Werten zu vereinfachen. So etwas wie

def myVar = "var" 

... 

flavor1 { 
    resValue "string", "my_res_string", "${myVar}" 
} 

flavor2 { 
    resValue "string", "my_res_string", "${myVar}" 
} 

Aber wenn mehrere Gegenden in der gleichen APK benötigt werden, und es wird zur Laufzeit von Android gewählt wird, dann ist die Zeichenfolge muss in den richtigen values-<locale> Ordnern.

+0

Jede Möglichkeit, dass wir eine Aufgabe verwenden können, um die Zeichenfolge res aus dem Build-Konfigurationsfeld vor dem Build zu ersetzen? – AndroidMechanic

+0

Du meinst also die Zeichenfolge ist für eine bestimmte APK festgelegt? Zum Beispiel eine APK nur für 'en_rUS' locale, andere nur für' pt_rBR', andere für 'ja'? Auf diese Weise ist es möglich. Wenn ja, werde ich meine Antwort aktualisieren. Was nicht möglich ist, haben mehrere Locales in der gleichen APK, wie das, was wir mit 'values-de',' values-pt', etc. machen. Dazu benötigen Sie den 'res /' Ordner –

+0

oh nein sorry my Schlecht. Ich habe es nicht durchdacht. Es tut uns leid! :) Es ist nicht behoben. benötigen Lokalisierungen für jedes Gebietsschema. – AndroidMechanic

1

Sie arbeiten hier auf verschiedenen Ebenen, BuildConfig ist Code, und als solcher nicht lokalisiert, deshalb haben wir Lint Warnungen für fest codierte Zeichenfolgen. Die Lokalisierung in Android erfolgt über <string Ressourcen, es gibt keinen Weg, wenn das System die Sprache zur Laufzeit abhängig von den Benutzereinstellungen auswählen soll. Es gibt jedoch viele Möglichkeiten, Ressourcen zu haben: values Ordner, resValue in build.gradle, und generierte Ressourcen.

Sie sollten in die buildSrc project in Gradle schauen, zum Beispiel verwende ich es, um SQL-Einsätze von src/main/values/stuff.xml zu generieren. Hier ist ein Code für den Anfang.

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 
      } 
     } 
    } 
} 

Dies ist nur das Skelett Sie können wild gehen und alles von hier aus tun: z eine CSV-Datei über das Netzwerk abrufen und den Inhalt in generierte variant*/res/values-*/gen.xml Dateien verteilen.

Sie können es manuell ausführen, wenn Sie benötigen oder es an der richtigen Stelle in den Build-Lebenszyklus laufen (in build.gradle:

android.applicationVariants.all { com.android.build.gradle.api.ApplicationVariant variant -> 
    variant.mergeAssets.dependsOn tasks.generateYourStuff 
} 
+0

danke! werde dies überprüfen, sobald ich zu Hause bin – AndroidMechanic

6

Meine andere Antwort über die generierten Ressourcen kann ein zu viel des Guten für Sie Fall verwenden . obwohl Basis, was ich zur Zeit über Ihr Projekt wissen ich denke, das ist eine bessere Passform: (nicht, dass Sie immer noch diese kombinieren mit generierten Ressourcen)

src/flavor1/res/Werte/strings.xml

<string name="app_name_base">InTouch Messenger"</string> 
<string name="app_name_gpe">InTouch Messenger: GPE Edition"</string> 

src/flavor1/res/Werte-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/Werte/strings.xml

<string name="app_name_base">Whatever Messenger"</string> 
<string name="app_name_gpe">Whatever Messenger: GPE Edition"</string> 

src/flavor2/res/Werte- 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" 
     } 
    } 
} 
Diese

bedeutet, dass flavor1/2 wird eine zusätzliche nicht verwendete app_name_gpe String-Ressource haben, aber das wird betreut von aapt genommen werden:

android { 
    buildTypes { 
     release { 
      shrinkResources true // http://tools.android.com/tech-docs/new-build-system/resource-shrinking 
     } 
+0

danke! werde dies überprüfen, sobald ich zu Hause bin – AndroidMechanic

+0

@AndroidMechanic hatten Sie etwas Glück mit beiden? – TWiStErRob

+0

Nein hat nicht funktioniert wie ich wollte. Habe jetzt separate xmls erstellt. Aber es sollte einen Weg geben. – AndroidMechanic

Verwandte Themen