Applanga Localization Command Line Interface (CLI)


Version: 1.0.43

Website: https://www.applanga.com

Changelog: https://www.applanga.com/changelog/cli


Table of Contents

  1. Installation
  2. Initialization
  3. Usage
  4. Configuration
  5. Configuration Examples

Installation

Manual
  1. Download and extract the latest client binary for your platform.

  2. Store the binary at a location where it can be found and executed by the system or adjust your PATH) accordingly

  3. You should now be able to execute it on the command-line like:

    applanga --help

or

    applanga.exe --help
Homebrew

On OSX we provide a homebrew tap to make the installation easier and up to date:

    brew tap applanga/cli
    brew install applanga

To update to the latest version call:

    brew upgrade applanga

Initialize Project

To initialize a new project the API token is needed. It can be found in the App under App Settings on the Applanga Dashboard.

The project can then be initialized by running the following in the project directory:

    applanga init

In the appearing dialog project data like the API token and the type of project will be requested. It will then save all the data to a configuration file into the current directory with the name .applanga.json

Push & Pull Translation Files

The translations can simply be pushed to and pulled from Applanga with the corresponding commands.

To pull translations from Applanga into local files:

    applanga pull
NOTE: The CLI is communicating with the Applanga API through our CDN to make sure the data is always reachable but that also means changes (including pushes) are only available to pull after a 10 minute delay even though they are already visible on the Dashboard!

To push existing local translations to Applanga:

    applanga push

Push Options

  • --force

By default values only get pushed if they aren't existing already on the dashboard to make sure not to accidentally overwrite translations. If you want to push local changed files you can do so with the --force option. But be cautios that this might overwrite values set ny a translator on the dashboard so be sure to pull before you push.

    applanga push --force
  • --draft

You can push values into that draft field to review them on the dashboard before you release them with the --draft option.

    applanga push --draft

Configuration

By default, the configuration file (.applanga.json) gets read from the current folder. It is however also possible to set an additional path to check for with the environment variable APPLANGA_CONFIG. If set it checks additionally also in its location. Additionally. can the configuration file be located in the home folder set in the environment variable HOME under Linux/Mac and HomePath under Windows.

Project Structure

The most basic configuration file generated after applanga init will look similar to this e.g. for a .po file:

{
    "app": {
        "access_token": "5b1f..!..2ab",
        "base_language": "en", 
        "pull": {
            "target": [
                {
                    "file_format": "gettext_po", 
                    "path": "./<language>.po"
                }
            ]
        }, 
        "push": {
            "source": [
                {
                    "file_format": "gettext_po", 
                    "path": "./<language>.po"
                }
            ]
        }
    }
}

If you are using multiple files, file formats on platforms that have different folders for their base languages or more complex folder structures like iOS or Android you'll need to modify the config as show in the configuration examples.

Target/Source Properties

There are a few mandatory and several optional properties that you can use to customize the cli to match your specific project setup.

Mandatory Properties:

  • "file_format"

    The file format specifies the format of the file that you want to push or pull wich typically depends on the platform that you are localizing.

    For a detailed format description check out the Applanga File Format Documentation

    Currently, the following formats are supported:

  • "path"

    In the "source" block it defines the files to upload and in "target" block the files to download. It is possible to set the variable <language> in the path. In the "source" block it will look for local files which have the language code set at its location (like: "en") and then upload the file for the found language. In "target" block it will replace it with the name of the languages which exist on Applanga and create the files accordingly.

    Example: "path": "./app/src/main/res/values-<language>/strings.xml"

Optional Properties:

  • "tag"

    Needed if you have multiple local files which is common on iOS and Android. If defined in the "source" block it will set the specified tag to all strings that are uploaded from the given "path". In the "target" block it will only download translations which have this tag applied. This is needed if you want to up and download only a subset of all available strings into or from certain files.

    Example: "tag": "main page"

  • "language"

    The language of the file. Is only needed if there is no placeholder <language> defined in "path" e.g. for your base "./values/" or "./Base.lproj/" folder.

    Example: "language": "en"

  • "exclude_languages"

    If you are using the placeholder <language> to download a file for all languages on the project it might be needed to exclude some languages from being pushed or pulled.

    Example: "exclude_languages": ["en", "de-AT"]

  • "export_empty" (target only)

    pull translations that are empty on the applanga dashboard which by default would get skipped. This property is only evaluated in the "target" block. This setting makes sense e.g. if you want the empty strings in your base language but not in the translations so they can fall back to the base strings or if you use the cli to pull files that you want to send to translators.

    Example: "export_empty": true

Configuration Examples


Android Configuration Examples

Basic Android App

The base Android strings are located in ./app/src/main/res/values/strings.xml, other languages are located in ./app/src/main/res/values-<language>/strings.xml. The following example shows the usage for a basic Android project with english set as base language.

{
    "app": {
        "access_token": "5b1f..!..2ab", 
        "base_language": "en", 
        "pull": {
            "target": [
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "export_empty": true,
                    "path": "./app/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "path": "./app/src/main/res/values-<language>/strings.xml"
                }
            ]
        }, 
        "push": {
            "source": [
                {
                    "language": "en",
                    "file_format": "android_xml", 
                    "path": "./app/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml", 
                    "path": "./app/src/main/res/values-<language>/strings.xml"
                }
            ]
        }
    }
}

Android App with Multiple Files & Submodule / Library

Apps can have strings in multiple files or in shared libraries. You can specify multiple files in the.applanga.json but to be able to up and download the subset of strings to the correct file you need to use the "tag" property so that Applanga can properly identify them.

{
    "app": {
        "access_token": "5b1f..!..2ab", 
        "base_language": "en", 
        "pull": {
            "target": [
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "export_empty": true,
                    "tag": "Main App Strings",
                    "path": "./app/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Main App Strings",
                    "path": "./app/src/main/res/values-<language>/strings.xml"
                },
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "export_empty": true,
                    "tag": "Other App Strings",
                    "path": "./app/src/main/res/values/other.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Other App Strings",
                    "path": "./app/src/main/res/values-<language>/other.xml"
                },
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "export_empty": true,
                    "tag": "Main Library Strings", 
                    "path": "./mylibrary/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Main Library Strings",
                    "path": "./mylibrary/src/main/res/values-<language>/strings.xml"
                }
            ]
        }, 
        "push": {
            "source": [
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "tag": "Main App Strings",
                    "path": "./app/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Main App Strings",
                    "path": "./app/src/main/res/values-<language>/strings.xml"
                },
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "tag": "Other App Strings",
                    "path": "./app/src/main/res/values/other.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Other App Strings",
                    "path": "./app/src/main/res/values-<language>/other.xml"
                },
                {
                    "language": "en",
                    "file_format": "android_xml",
                    "tag": "Main Library Strings", 
                    "path": "./mylibrary/src/main/res/values/strings.xml"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "android_xml",
                    "tag": "Main Library Strings",
                    "path": "./mylibrary/src/main/res/values-<language>/strings.xml"
                }
            ]
        }
    }
}

iOS Configuration Examples

Basic iOS App

If Base Localization is enabled the base iOS strings are located in ./Base.lproj/Localizable.strings, other languages are located in ./<language>.lproj/Localizable.strings. The following example shows the usage for a basic iOS project with english set as base language.

{
    "app": {
        "access_token": "5b1f..!..2ab", 
        "base_language": "en", 
        "pull": {
            "target": [
                {
                    "language": "en",
                    "file_format": "ios_strings",
                    "export_empty": true,
                    "path": "./Base.lproj/Localizable.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings",
                    "path": "./<language>.lproj/Localizable.strings"
                }
            ]
        }, 
        "push": {
            "source": [
                {
                    "language": "en",
                    "file_format": "ios_strings", 
                    "path": "./Base.lproj/Localizable.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings", 
                    "path": "./<language>.lproj/Localizable.strings"
                }
            ]
        }
    }
}

iOS App with Pluralization .stringsdict and Storyboard .strings

If you turn on localization on your storyboards you will end up with a .strings file for every storyboard in every language and since strings on the Applanga dashboard are merged to one big list you need to use the config "tag" property to tag the strings for the specific files on push and pull so you can identify them later on. To extract the .strings from your storyboard you can use the following command

ibtool MainStoryboard.storyboard --generate-strings-file MainStoryboard.strings

For Pluralization apple introduced the .stringsdict File Format which you can also conveniently push and pull with the Applanga command line interface. A .stringsdict file always need an accompanying .strings file so you can use the same tag for both.

{
    "app": {
        "access_token": "5b1f..!..2ab", 
        "base_language": "en", 
        "pull": {
            "target": [
                {
                    "language": "en",
                    "file_format": "ios_strings",
                    "tag": "Localizable.strings",
                    "export_empty": true,
                    "path": "./Base.lproj/Localizable.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings",
                    "tag": "Localizable.strings",
                    "path": "./<language>.lproj/Localizable.strings"
                },
                {
                    "language": "en",
                    "file_format": "ios_stringsdict",
                    "tag": "Localizable.strings",
                    "export_empty": true,
                    "path": "./Base.lproj/Localizable.stringsdict"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_stringsdict",
                    "tag": "Localizable.strings",
                    "path": "./<language>.lproj/Localizable.stringsdict"
                },
                {
                    "language": "en",
                    "file_format": "ios_strings",
                    "tag": "MainStoryboard.strings",
                    "export_empty": true,
                    "path": "./Base.lproj/MainStoryboard.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings",
                    "tag": "MainStoryboard.strings",
                    "path": "./<language>.lproj/MainStoryboard.strings"
                }
            ]
        }, 
        "push": {
            "source": [
                {
                    "language": "en",
                    "file_format": "ios_strings",
                    "tag": "Localizable.strings",
                    "export_empty": true,
                    "path": "./Base.lproj/Localizable.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings",
                    "tag": "Localizable.strings",
                    "path": "./<language>.lproj/Localizable.strings"
                },
                {
                    "language": "en",
                    "file_format": "ios_stringsdict",
                    "tag": "Localizable.strings",
                    "path": "./Base.lproj/Localizable.stringsdict"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_stringsdict",
                    "tag": "Localizable.strings",
                    "path": "./<language>.lproj/Localizable.stringsdict"
                },
                {
                    "language": "en",
                    "file_format": "ios_strings",
                    "tag": "MainStoryboard.strings",
                    "path": "./Base.lproj/MainStoryboard.strings"
                },
                {
                    "exclude_languages": ["en"],
                    "file_format": "ios_strings",
                    "tag": "MainStoryboard.strings",
                    "path": "./<language>.lproj/MainStoryboard.strings"
                }
            ]
        }
    }
}