12

Это в продолжение к ответу, который помог мне на this postЛокализующие строковые ресурсы добавлены с помощью build.gradle с помощью «resValue»

Мы можем добавить строковый ресурс, как следует из 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 (не представляется возможным из-за нескольких способов, в которых мой проект структурированный)

+2

Я думаю, что если вам нужно локализовать, то, вероятно, не должно быть град. Основное использование там состоит в том, чтобы иметь, например, два разных ключа API, один для Prod, один для Dev. – hmartinezd

+0

в моем случае ароматы продукта не для сред, а для разных вариантов приложения. все из которых идут на производство. Моя среда контролируется с помощью типа сборки. Не могу пойти с отдельным xml для каждого аромата, потому что у меня их много и когда-либо возрастает. Следовательно, решил сделать это через град. – AndroidMechanic

+0

Извините за предоставление решений 'strings.xml', но я не думаю, что вы можете сделать это иначе. Если у вас есть проблемы с разделением, вы можете добавить разные 'res.srcDir' на основе того, что вы локализуете, но добавляемая вами папка может содержать несколько файлов значений - /strings.xml'. – TWiStErRob

ответ

3

Если вам не нужно работать с этими строками, лучший вариант переместится на strings.xml, но это сделает вас делить все папки res между ароматами. Если вы создаете эти строки на основе некоторого свойства на build.gradle, то я думаю, что вам не повезло, к сожалению.

EDIT:уточняя, что я имею в виду работать выше, и добавить некоторые опции:

По , работающим на этих строках я имею в виду какое-то конкатенация с параметром сборки, чтение из команды line или environment во время процесса сборки (например, получение SHA1, чтобы было легче отслеживать ошибки позже). Если никакой операции не требуется, может быть вариант strings.xml. Но когда вы переписываете папку res для аромата, все это перезаписывается, и это может создать проблему, если несколько ароматов имеют один и тот же res, за исключением ограниченного количества строк.

Если у каждого АПК есть своя локаль, то это всего лишь resValue или buildConfigField в аромате. Вы можете определить переменные для более простого повторного использования значений. Что-то вроде

def myVar = "var" 

... 

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

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

Но если несколько локалей необходимы в том же APK, и он будет выбран во время выполнения Android, то строка должна быть в правильной values-<locale> папке.

+0

Любая возможность использовать задачу для замены строки res из поля конфигурации сборки до сборки? – AndroidMechanic

+0

Вы имеете в виду, что строка фиксирована для данного APK? Например, один APK только для 'en_rUS' locale, другой только для' pt_rBR', другой для 'ja'? Таким образом, да, это возможно. Если это так, я обновлю свой ответ. Невозможно иметь несколько локалей в одном APK, например, что мы делаем с 'values-en',' values-pt' и т. Д. Для этого вам понадобится папка 'res/' –

+0

oh no sorry my Плохо. не подумал. Прости! :) Это не исправлено. нужны локализации для каждой локали. – AndroidMechanic

1

Здесь вы работаете на разных уровнях, BuildConfig - это код и, как таковой, не локализованный, поэтому у нас есть предупреждения Lint для жестко закодированных строк. Локализация в Android выполняется через ресурсы <string, нет никакого способа обойти это, если вы хотите, чтобы система выбирала язык во время выполнения в зависимости от пользовательских настроек. Есть много способов иметь ресурсы: values папка, resValue в build.gradle и сгенерированные ресурсы.

Вы должны изучить buildSrc project in Gradle, например я использую его для создания SQL-вложений от src/main/values/stuff.xml. Вот какой код для начала.

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/Главный/заводной/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/Главный/заводной/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 
} 
+0

спасибо! проверит этот, а также как только я дома – AndroidMechanic

6

Моего другой ответ о сгенерированных ресурсах может быть избыточен для вас использовать случай . хотя база, что я в настоящее время известно о вашем проекте, я думаю, что это один лучше подходит: (не то, что вы все еще можете совместить это с сгенерированных ресурсов)

SRC/flavor1/RES/значения/strings.xml

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

SRC/flavor1/RES/значения-ху/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/значения/strings.xml

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

SRC/flavor2/RES/с ценностно 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 
     } 
+0

спасибо! проверит это, как только я приду домой – AndroidMechanic

+0

@ AndroidMechanic вам повезло? – TWiStErRob

+0

Нет, не так, как я хотел. Создали отдельные xmls сейчас. Но вокруг этого должно быть что-то. – AndroidMechanic

Смежные вопросы