Localazy Gradle plugin

The Localazy Gradle plugin helps you to upload strings and to integrate Localazy into your app.

The plugin overview

The plugin has several important functions:

  • it integrates tightly with the Android Gradle plugin to understand your project’s structure
  • it uploads strings including metadata about flavors, build types, etc. to the translation platform
  • it integrates the Localazy Android library into the bytecode of your app so translations can be updated on-the-fly
  • while building your app, it replaces app’s resources with updated translations

Also, when the Localazy Android library is integrated into your app, it collects stats to improve translations and to suggests languages you should translate your app into, etc.

No changes to your code

We are committed to a simple rule “No changes to your code” which means two important things:

We never touch your source code and resources. No exceptions. All modifications to your app take place during the build process and are applied to intermediate files. The plugin also respects your project’s structure and should work correctly with any project layout, including different product flavors, build types, etc.

No work on your side. Under normal circumstances, there is no extra action needed except for adding the plugin and the Android library to your build scripts. Our defaults are suitable for the majority of apps, and no changes in your source code are needed to have your app translated with Localazy.

As a result, it’s easy to try Localazy out, and you can be sure that your project stays unmodified.

Compatibility

The plugin is compatible with native Android apps written with Java, Kotlin and other JVM-based languages.

Your project must be built using Gradle with Android Gradle plugin (com.android.tools.build:gradle) of at least version 3.5.0+.

If you use Android Studio for building your app, you should be good to go.

Quick start

1. Open Android Studio, locate gradle.build file in your project’s root directory and add Localazy repository and Gradle plugin to the buildscript section.

buildscript {

    repositories {
        // ... other repositories ...
        maven { url "https://maven.localazy.com/repository/release/" }
    }

    dependencies {
        // ... other dependencies ...
        classpath "com.localazy:gradle:1.5.2"
    }

}

2. Open gradle.build file in your app’s module and add following snippet a the end of the file:

// Always be sure to add this after android { ... } section
apply plugin: 'com.localazy.gradle'

localazy {
    readKey "the-read-key-for-the-project"
    writeKey "the-write-key-for-the-project"
}

Read more about injection options to configure what type of library is injected and whether OTA updates are available for all users or loyal ones only.

And that’s it! Your app is translated, and translations are updated automatically.

Configure the plugin

Our defaults are suitable for the majority of apps, and extra configuration is usually not necessary except for small tweaks (excluding particular strings, disabling errors for debug builds, etc.)

The configuration of the plugin looks like:

localazy {

    readKey "the-read-key-for-the-project"
    writeKey "the-write-key-for-the-project"

    upload {
        // ...
    }

    download {
        // ...
    }

    injection {
        // ...
    }

    resources {
        // ...
    }

}

localazy

The localazy section serves as the main configuration and contains all other options related to the plugin.

Name Type Default Description
readKey string none The read key to use for downloading updated translations into the app and for sending stats.
writeKey string none The write key to use for uploading strings for translating.
addPrefix boolean false Adds prefix [LL] for all strings processed by Localazy OTA engine, so you can verify that the whole app is correctly translated. It’s also useful when developing custom view transformers.
allowAllLibraries boolean false 1.3.0+ Enables an experimental support for libraries with different build types and product flavors.
upload struct none Configures string uploading. See upload.
download struct none Configures string downloading. See download.
injection struct none Configures the library injection. See injection.
resources struct none Configures resources injection. See resources.
copyFrom project none Defines another module to copy configuration from. It’s useful for integrating libraries, so you don’t need to define the configuration again. Please keep in mind, that it only copies unchanged values. It doesn’t copy data from the upload section as the upload is always process by the app’s module only.

You can find read and write keys in your app’s Settings > Access Keys.

Defining keys in local.properties

You can define read and write keys in local.properties, so they are not commited to the version control system.

This is especially useful for open-source software with publicly available repositories.

# Path to Android SDK is typically defined here.
sdk.dir=/home/user/path/to/android

localazy.readKey=your-app-read-key
localazy.writeKey=your-app-write-key

You can define the keys also in gradle.properties the same way.

Copying the configuration to library

To apply Localazy correctly to your library modules, you have to include them in the projects of the upload section and apply the Localazy Gradle plugin to them. However, the configuration is not, by default, shared between modules and so you would need to configure the library module again. With the copyFrom option, you can transfer configuration from your app’s module like this:

apply plugin: 'com.localazy.gradle'

localazy {
    copyFrom project(":app")
}

upload

The upload section configures how strings are uploaded from your app to the Localazy platform. The default configuration is suitable for the majority of apps, and under normal circumstances, you don’t need to make any changes.

Name Type Default Description
deprecateMissing boolean true If set to true, strings that are not contained in the batch are marked deprecated.
defaultLang string inherited The language of values folder. Special value inherited means to use the project’s default language as defined in the Localazy platform. The language must be one recognized be the Localazy platform in format xx (eq. cs, en, de) or xx_XX (eq. cs_CZ, en_US).
defaultState string current If set to current, uploaded strings are automatically used as a translation of choice if no translation is available. If set to new, uploaded strings are uploaded as non-approved and must go through the review process - this is important if you are not sure of the translation quality.
showUploadAll boolean false If set to true, Gradle tasks uploadAllStrings and uploadBaseStrings are available instead of uploadStrings only.
strictMode boolean false 1.4.0+ If set to true, the pre-upload analysis ends with error if there are some possible issues detected.
ignoreMissingDefault boolean false If set to true, the plugin ignores missing default translations in flavors, which may lead to the phrase not appear correctly in the Localazy platform.
ignorePrivateStrings boolean false If set to true, the plugin ignores private strings analysis. By default, Localazy warns you if the string seems to be ad identifier, etc. and prevents upload.
strings struct n/a Allows to include or exclude string keys in the upload. See strings.
files struct n/a Allows to include or exclude files with strings in the upload. See files.
projects struct n/a Allows to include projects that should be included in the upload. See projects.
analysis struct n/a 1.3.0+ Allows to exclude strings from pre-upload analysis. See analysis.
include struct n/a 1.4.0+ Allows to manually include strings that are excluded by the analysis. See include.

Use strings and files to exclude API keys, tokens, ad placement ID, Facebook’s app ID, etc.

strings

Allows to include or exclude particular strings from uploading. You can include or exclude strings that match the given pattern, and it’s possible to use wildcard symbols * and ?.

By default, all strings are included except for those that are explicitly excluded here. If at least one include is used, the resolution process is switched to the include-only mode, which means that all strings are excluded by default except for those explicitly included. Excluding has higher a priority than including.

localazy {
    upload {
        strings {

            // Include key_1, apply to all subprojects
            include "key_1"

            // Include key_1 from anotherProject subproject
            include project(":anotherProject"), "key_1"

            // Exclude key_2, apply to all subprojects
            exclude "key_2"

            // Exclude key_2 from anotherProject subproject
            exclude project(":anotherProject"), "key_2"

        }
    }
}

To use inclusion or exclusion of sub-project strings, you need also to add the given sub-project in the projects section.

files

Allows to include or exclude particular files from uploading. You can include or exclude files that match the given pattern, and it’s possible to use wildcard symbols * and ?.

By default, all files are included except for those that are explicitly excluded here. If at least one include is used, the resolution process is switched to the include-only mode, which means that all files are excluded by default except for those explicitly included. Excluding has a higher priority than including.

The file path to be matched is in a special format allowing for precise selection of included/excluded resources. The format is flavorName:folder/file.ext, which means that it’s usually something like main:values/strings.xml.

localazy {
    upload {
        files {

            // Include strings_specific.xml from all subprojects, folders and flavors
            include "*/strings_specific.xml"

            // Include strings_specific.xml from flavor free, folder values-v11 and project anotherProject
            include project(":anotherProject"), "free:values-v11/strings_specific.xml"

            // Exclude strings_private.xml, apply to all subprojects, folders and flavors
            exclude "*/strings_private.xml"

            // Exclude strings_private.xml from flavor free, folder values-v11 and project anotherProject
            exclude project(":anotherProject"), "free:values-v11/strings_private.xml"

        }
    }
}

To use inclusion or exclusion of sub-project strings, you need also to add the given sub-project in the projects section.

projects

Allows to include extra Gradle projects (modules in Android Studio) when uploading strings. The project/module this configuration is placed inside is always included.

It’s useful to include projects when you need to translate also strings from your libraries, etc.

localazy {
    upload {
        projects {
            include project(":anotherProject")
        }
    }
}

analysis

Allows skipping strings with listed keys from the pre-upload analysis that checks your strings for those that you are likely to exclude from the upload, and those that don’t have default translation.

You can disable the analysis completely using ignoreMissingDefault and ignorePrivateStrings.

It’s possible to use wildcard characters * and ?.

localazy {
    upload {
        analysis {
            skip "key_1"
            skip "key_2"
            skip "key_3"
        }
    }
}

include

Allows manual including of strings that are excluded by the pre-upload analysis because they may contain private or sensitive data.

It’s possible to use wildcard characters * and ?.

localazy {
    upload {
        include {
            string "key_1"
            string "key_2"
            string "key_3"
        }
    }
}

download

The download section tells the plugin on how to download data and how to behave if data or the internet connection is not available. The downloaded data are cached and used when building the app.

Name Type Default Description
enabledForRelease boolean true If set to true, download new strings from Localazy for release builds.
enabledForDebug boolean true If set to true, download new strings from Localazy for debug builds.
errorOnFailureRelease boolean true If set to true, fail if data cannot be downloaded for release builds. If false, silently ignore the problem and show a warning. We strongly discourage you from settings this option to false!
errorOnFailureDebug boolean true If set to true, fail if data cannot be downloaded for debug builds. If false, silently ignore the problem and show a warning.
redownloadInterval long 3600 Configures how often to re-download data from Localazy in seconds. The minimum is 900 seconds.

injection

The injection section allows you to configure how the Android library is integrated into your app.

Name Type Default Description
enabledForRelease boolean true If set to false, the code injection of the Android library is disabled for release builds.
enabledForDebug boolean true If set to false, the code injection of the Android library is disabled for debug builds.
library string androidx 1.3.0+ Automatically adds the Localazy Android library as dependency. Allowed values are none (don’t add library), androix (add AndroidX version), plain (add plain Android version), support (add version with the legacy support libraries).
dontUpdateForDebug boolean false 1.2.1+ If set to true, OTA updates and stats collecting is disabled for the development/debug builds.
dontCheckInternetPermission boolean false 1.3.0+ If set to true, the plugin doesn’t check whether INTERNET permission is granted to the app.
updateInterval int 86400 1.2.0+ How often to check for new translations in seconds. Minimal value is 3600.
updateIntervalForFailure int 14400 1.2.0+ How often to check for new translations in seconds if the previous request failed. Minimal value is 900.
updateDelay int 0 1.2.0+ How many seconds to delay the first check for new translations. By settings this value, you can filter out users that install the app and remove it almost immediately.
statsInterval int 86400 1.2.0+ How often to send collected stats to our servers. Minimal value is 900.
statsIntervalForFailure int 14400 1.2.0+ How often to send collected stats to our server if the previous request failed. Minimal value is 900.
statsDelay int 300 1.2.0+ How many seconds to delay the first sending of collected stats. By settings this value, you can filter out users that install the app and remove it almost immediately.
minimalStatsSize int 2048 1.2.0+ Defines the minimal size of the collected stats package before it’s sent to our servers in bytes. Keep this small to receive stats from users.
maximalStatsSize int 262144 1.2.0+ Defines the maximal size of the file for collecting stats. There are three files for stats, so Localazy needs storage equal to 3 x maximalStatsSize. If the maximal size is reached, stats are no longer collected until successfully sent to our servers.
updateForActivityOnly boolean true 1.2.0+ If set to true, translations are only updated when Activity is shown. It prevents unwanted updates (and lower the number of DAU requests) from background services and receivers.
sendStatsRegularly boolean false 1.2.0+ If set to true, collected stats are sent to our servers periodically. If set to false, collected stats are only sent after a translation update request (no matter if translations were updated or not). It prevents too many requests to our servers and thus lowers the number of DAU requests (and your price). If set to false, statsInterval, statsIntervalForFailure and statsDelay are ignored.
enableApplicationTransform boolean false If set to true, the code injection is applied also to subclasses of android.app.Application. This is generally not needed and there are known issues with Firebase when enabled. Enable this only if you really need it.
exclude method n/a Allows excluding classes from the injection process. See exclude.
installRepositories boolean true 1.3.0+ Automatically install Localazy repository to all subprojects of the root project, so you don’t need to do so manually.
loyalUsersOnly method n/a 1.3.0+ Call this method to set updateInterval, updateIntervalForFailure, updateDelay and other options to values suitable for delivering updates to only long-term loyal users.

If the injection is disabled, Localazy can’t update translations on-the-fly and can’t optimize how your app is translated!

If you do changes to injection settings, be sure to clean and rebuild your project.

exclude

The injection process modifies the bytecode of produced class files. You can exclude classes for which the injection process is undesired. To exclude class, you specify its fully qualified name or use wildcard * for a single path segment or ** for everything.

It’s normally not necessary to exclude classes, and you shouldn’t do so unless there is a good reason for it.

localazy {
    injection {

        // Exclude class com.localazy.test.Class1
        exclude "com.localazy.test.Class1"

        // Exclude any class in package com.localazy.test but NOT in subpackages
        exclude "com.localazy.test.*"

        // Exclude any class in package com.localazy.test and all subpackages
        exclude "com.localazy.test.**"

        // Exclude class Class1 in any package
        exclude "**.Class1"

        // Define more rules with a single line
        exclude "package.Class1", "package.Class2", "package.Class3"

    }
}

Take care when excluding classes as it may cause undesired effects and incomplete translation of your app.

resources

With Localazy, you don’t need to download XML files manually. The plugin overwrites all strings in your app with the most recent version from the translation platform. It also adds languages that are available in Localazy but not in your app.

It never changes your source code nor your XML resources. All changes take place during the compilation only while the Android Gradle plugin merges resources.

The resources section configures how your resources are updated with new translations.

Name Type Default Description
enabledForRelease boolean true If set to true, your string resources are automatically merged with new strings from Localazy for release builds.
enabledForDebug boolean true If set to true, your string resources are automatically merged with new strings from Localazy for debug building.
failOnMissingDataRelease boolean true If set to true, the build process fails if data are missing and cannot be merged with release builds. If false, resources are not updated, and this step is silently skipped. We strongly discourage you from settings this option to false!
failOnMissingDataDebug boolean true If set to true, the build process fails if data are missing and cannot be merged with debug builds. If false, resources are not updated, and this step is silently skipped.

If you do changes to resources settings, be sure to clean and rebuild your project.

Uploading strings

When the plugin is configured, new Gradle tasks are available for uploading strings to the translation platform.

uploadStrings

When used for the first time / in a new project, upload strings in all languages for translation.

Subsequent uses upload only changes to the base language as all future changes to strings should be made only to the base language.

This task uses hidden .localazy file in the project directory to store state information.

Not available if upload.showUploadAll is set to true.

uploadBaseStrings

Upload strings in the base language for translation.

For the first time, you should upload your strings in all languages with uploadAllStrings. Then, do changes to the base language only and use this task to upload changes for translation.

Only available if upload.showUploadAll is set to true.

uploadAllStrings

Upload strings in all languages for translation.

This should be used only for the first time. In the future, you should add new strings to the base language only and upload changes with uploadBaseStrings.

Only available if upload.showUploadAll is set to true.

Frequently asked questions - Learn more about advanced topics related to Localazy Gradle plugin.

Localazy Android library - Dive deeper into the magic; there’s more you can do with Localazy.

What you should know before uploading strings - Learn more about key aspects to consider if you are serious about translating your app.