Software Localization Projects in Smartcat (developer portal)

In addition to regular document-based projects, Smartcat offers a different way of managing keys (strings) that is more suitable for software localization projects.

  1. Software keys (strings) are managed on the platform (Smartcat becomes the source of truth for all of your software copy)

  2. UX writers and product managers change the copy by themselves, without distracting developers

  3. Developers act as content consumers by exporting the needed subset of keys in a format of their choice

  4. Developers can import source strings and translations in various developer file formats, and export translations in various file formats as well

  5. REST API and CLI offer easy integration with CI/CD pipelines

Here is a typical workflow for a software localization process:

  1. Create collections that will contain keys with unique identifiers

  2. Import keys via API into an existing or new collection (JSON, YAML, iOS Strings, Android XML and LocJSON). You can do this in the beginning only to populate the initial project data. 1. Keys with ICU MessageFormat syntax can be converted to individual segments with plural forms or imported as is 1. You can add labels to all imported segments

  3. Create or modify keys (segment source and identifiers) inside the CAT editor 1. You can create new keys with plural forms right in the editor 1. You can add labels to segments in the editor 1. Upload screenshots or provide additional context information for segments right from the editor

  4. Translate content, assign suppliers using tasks as with usual projects

  5. Export keys via API or UI from the Editor (JSON, YAML, iOS Strings, Android XML). Plural forms will be converted to ICU MessageFormat syntax

  1. JSON

  2. YAML

  3. Android XML

  4. iOS Strings

  5. LocJSON (see below)

LocJSON is a JSON-based file format that Smartcat uses for integration purposes. It is extendable, and allows external integrations to pass a list of units (keys + source text + optional translations), and associate metadata with each unit, like comments or maximum string length per each unit. Smartcat will automatically identify this format by file extension,.locjson.

  1. JSON (flat or structured)

  2. YAML (flat or structured)

  3. Android XML

  4. iOS Strings

  1. On the home page, click on the Create software localization project option. ![project creation](https://lh7-us.googleusercontent.com/ogdIdnYBqDG9KKje9GPKtfH3qIQHfWlD4I3s_fLJ1xcrk2nVhYGtAWkohNPW_OCg199Ca_2o1RSXYyMIB1UcoQmujaC0mf7_kSnf-mb4ee7N5Ho8GMHQdB4M9lYIeo3s7CoY_8a6jsZsQdY0_L5QB2dFzDhYPqZ1 "")

  2. Enter project name, e.g. My App, and specify one source language and a list of target languages, and press Create project. ![project wizard](https://lh7-us.googleusercontent.com/ZA_sgeWTDMO1b7bH4GE2U9-fZiLsJOkOyMgAAmTCBZEVTsw53otPtIxivhmmUbRAXh_qAQ84HpGLv5g7ZLZA9xxdnS3CyS7GnN3slp9Bt1t0tiCXheoppaF6yMeaWL-QAeAF86plRkRAdpdbPoOhHpUBWGDvQX5T "")

👉 You will be able to change the list of target languages later at any time, but you can have only one source language for a project, and source language cannot be changed once the project is created.

Once the project is created, you will see a project Overview page. A default collection called main will be created and selected automatically.

Smartcat supports the following ways to import your existing keys from various file formats:

  1. Using Smartcat CLI

  2. Using our public API (and standard tools like curl)

  3. Directly through Smartcat UI.

Similarly, the same methods are support for exporting:

  1. Using Smartcat CLI

  2. Using our public API (and standard tools like curl)

  3. Directly through Smartcat UI.

Smarcat CLI (command-line interface) is a tool available for all popular platforms (Windows, MacOS, Linux) that you can run from command line (console) and from CI/CD scripts to perform certain actions automatically. Read more about the CLI here: Smartcat CLI.

Per-Folder Configuration File

As a matter of convenience, you can create a file called.smartcat in the folder you will be runnung Smartcat CLI from. In this file you can put information about your Smartcat server, workspace, project, and API key (all fields are optional).

Example file

{

"Server": "https://smartcat.com",

"Workspace": "fd104ef5-cbe7-1459-c8ac-237d99a3c614",

"Project": "446dfcf0-e699-4c91-a7ee-40e1237a9f81",

"ApiToken": "1\_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

}

Once you do so, this information will override your user settings.

Such a configuration file will allow you to skip specifying --project xxxxxxxx in every CLI command invocation.

Import

smartcat import en/strings.json --language en --label android

Importing keys is done with the smartcat import command. This example shows the actual project identifier, and you can use it as a starting point. If you have a file called en/strings.json (paths can be relative to your current directory), then the following command will import all the keys from that JSON file into your newly created project into the main collection (which is the default collection name), while also giving the android label to all imported keys.

smartcat import zh-Hans/strings.json --language zh-Hans

Similarly, you can import translations from an existing file that has the same keys:

👉 Run smartcat import --help for a list of all available import options.

Export

Exporting is performed through smartcat export command. The following example will export specified target languages and give them file names as defined in the output template.

smartcat export --languages es,zh-Hans --output-file-path-template 'strings-{LANGUAGE}.json'

👉 Run smartcat export --help for a list of all available export options.

👉 Most topics regarding authentication and basic API usage are described here: https://developers.smartcat.com/en/api-guides/ — please check this documentation before proceeding. API Reference for import/export is below. API Reference for other API methods is available at https://developers.smartcat.com/en/api/

Please find all the API methods for the import/export key feature in the Postman collection below.

Postman Collection with API Examples

For your convenience, we have created a Postman collection of API requests that you can easily experiment with:

Before using the examples, you need to update values for several variables using in this collection:

  1. accountID can be obtained from your Smartcat workspace (see Settings > API)

  2. apiToken can be generated on the same Settings > API page

  3. apiServer is one of the servers your workspace is located on (you can look up the domain you see when working with your workspace). It can be one of the following: 1. smartcat.com (Europe) 1. us.smartcat.com (USA) 1. ea.smartcat.com (Asia)

  4. projectID is the ID of the project you will be running import/export against. Once you create a project, it’s URL will be something like https://smartcat.com/projects/6c58e1f5-61c6-43dc-9b83-8d635edbd50c/overview. Here, 6c58e1f5-61c6-43dc-9b83-8d635edbd50c is the project ID.

Step 1. Use the import API call (see the provided Postman example called Import keys) to import the following document into a newly created project:

This will automatically create a collection called main in that project.

Step 2. Open the Files tab in your project, where you will see main collection. Click on its name to open in the editor. Here you can add new keys, and edit or delete existing ones.

Step 3. Import one of these files using the same import API call to add or update keys (this way you will merge changes from those files into your collection of keys):

Step 4. Export translated keys back. Export is a two-step process:

  1. Export request (see the provided Export keys Postman example). Here you specify the needed set of languages and the output file format. This request returns the ID of the asynchronous export task, which will be automatically captured by the Postman automation script.

  2. Download request (see the provided Download export results Postman example). This will return the contents of your file. If you request just one language, the document will be returned as is in the response body. If you request multiple documents, you will get a ZIP file with multiple files inside.

Import

Code samples

POST /api/integration/v2/project/{projectId}/import` HTTP/1.1

Content-Type: multipart/form-data

Accept: text/plain

POST /api/integration/v2/project/{projectId}/import

Starts async import multiple files to given project and branch. The body consists of a number of parts with the following headers:

Content-Disposition: form-data; name="file"; filename="path/to/file"

Content-Type: text/plain

Parameters

Name

In

Type

Required

Description

projectId

path

string(uuid)

true

Project identifier

collection

query

string

false

Target collection (optional, "main" as default)

language

query

string

false

Language of the imported files

target-languages

query

string

false

Comma separated list of target languages

format

query

string

false

Specifies the file format used to import the file (optional).

completion-state

query

string

false

Imported translation confirmation mode

labels

query

string

false

Comma-separated labels that will be attached to the created/updated segments (even if the text is not changed)

path-separator

query

string

false

Path separator string (optional)

skip-conflicting-values

query

boolean

false

Specifies how to deal with situations when the same key has a different

overwrite-conflicting-values

query

boolean

false

When the same key has a different value in the imported file and in Smartcat - use the value from the file

auto-file-labels

query

boolean

false

Should Smartcat automatically create labels after file names?

delete-missing-keys

query

boolean

false

Delete keys that are not present in the imported files

body

body

UploadedFile

true

Files for import

Detailed descriptions:

format — specifies the file format used to import the file. Smartcat will try to guess the file format from its extension:

  1. json — flat key-value format

  2. structured-json — tree-like format; see also: path-separator

  3. yaml — flat key-value format

  4. structured-yaml — tree-like format; see also: path-separator

  5. ios-strings — iOS.strings resource file format

  6. android-xml — Android XML resource file format

path-separator — path separator string, used to construct keys for nested JSON objects (defaults to “/”). Consider the following example JSON file - when the “value” string will be imported, it’s key name will be “object/my-key”.

target-languages: Comma separated list of target languages (optional, all target languages of the project by default, can only be specified when importing the source).

  1. Empty list of languages produces a 400 bad request error with an appropriate reason text

  2. An incorrect language code produces a 400 bad request error with an appropriate reason text

  3. If any language didn't exist in the project, it will be created (but not added as a target to any existing collections)

  4. If any language didn't exist in the collection (the target collection existed before), it will be added as a target to the collection

completion-state: Imported translation confirmation mode

  1. draft - no confirmation

  2. intermediate - confitm on the first project stage

  3. final - confirm on all project stages

Example JSON file

{

"object": {

"my-key": "My value"

}

}

Responses

Status

Meaning

Description

Schema

200

OK

Request has been successfully completed

Response with the import ID

400

Bad Request

See the detailed description below

None

403

Forbidden

See the detailed description below

None

HTTP 400 returns if:

  1. Required 'language' parameter missing

  2. The input (request body) contains no files

  3. 'skip-conflicting-values' and 'overwrite-conflicting-values' parameters are specified at the same time. Choose one option

  4. Passed language is completely unrecognizable by Smartcat

  5. Passed language is neither a source language nor one of target languages

  6. The 'format' value is invalid. Allowed values are: 'json', 'yaml', 'ios-strings', 'android-xml', 'locjson'.`

  7. The 'path-separator' parameter is specified for any file format other than 'json' or 'yaml'

HTTP 403 returns if:

  1. The requested project does not belong to the authenticated account

  2. Trying to import into a non-developer project

  3. Trying trying to import into a personal account

Get Import Result

GET api/v1/project/import-result/{importId}` HTTP/1.1

Accept: text/plain

GET api/v1/project/import-result/{importId}

Returns current import status if the import task exists.

Result model

{

"status": "pending" | "inprogress" | "completed" | "failed",

"errors": { "error": "string", "fileName": "string" }[],

"keysCreated": 0,

"keysUpdated": 0,

"keyValuesNotChanged": 0,

"keysWithoutSource": 0,

"conflictingKeyValues": {

"key1": ["valueA", "valueB"],

"key2": ["valueC"],

}

}

Responses

Status

Meaning

Description

Schema

200

OK

Request has been successfully completed

Returns current import status

404

Not Found

The export ID doesn't exist

None

Export

POST /api/integration/v2/project/{projectId}/export` HTTP/1.1

Content-Type: multipart/form-data

Accept: text/plain

POST /api/integration/v2/project/{projectId}/export

Starts async export multiple files to given project and branch. Returns HTTP 200 with export ID if export has started.

Parameters

Name

In

Type

Required

Description

languages

query

string

false

Comma-separated list of languages to export (allow multiple, all target languages as default)

collections

query

string

false

Export from one collection (main as default)

path-separator

query

string

false

Path separator string, used to reconstruct nested JSON objects (defaults to “/”)

completion-state

query

string

false

Minimal key completion state (final by default)

fallback-to-default-language

query

string

false

Incomplete translations: download segments that passed through all translation stages (default)

export-incomplete-as-blank

query

string

false

Incomplete translations: export blank values when no translation is ready

skip-incomplete-keys

query

string

false

Incomplete translations: do not export keys that have no translations (will be used as a default for "android-xml" export file type)

format

query

string

false

Export format (json by default)

include-default-language

query

string

false

Should the default language be included in the export?

output-file-path-template

query

string

false

output file path template

zip

query

string

false

Force export in a ZIP archive, even when downloading a single file

modified-since

query

string(date-time)

false

Export keys that were changed after the datetime

labels

query

string

false

Comma-separated list of labels to export keys that are marked with labels

path-separator — path separator string, used to reconstruct nested JSON objects (defaults to “/”). If there’s a key “object/my-key” with the value of “My value”, then exporting a structured JSON file would give the result you can see to the right.

Structured JSON file export result

{

"object": {

"key": "value"

}

}

completion-state — minimal key completion state (final by default):

  1. final — download segments that passed through all translation stages (default)

  2. intermediate — download segments at the last confirmed stage

  3. draft — download any translations, even unconfirmed ones

What to do with incomplete translations:

  1. fallback-to-default-language — return default language values instead of translations (default)

  2. export-incomplete-as-blank — export blank values when no translation is ready

  3. skip-incomplete-keys — do not export keys that have no translations (will be used as a default for "android-xml" export file type)

format — export format (json by default):

  1. json — flat key-value format (default)

  2. structured-json — tree-like format; see also: path-separator

  3. yaml — flat key-value format

  4. structured-yaml — tree-like format; see also: path-separator

  5. ios-strings — iOS.strings resource file format

  6. android-xml — Android XML resource file format

Responses

Status

Meaning

Description

Schema

200

OK

Request has been successfully completed

Returns export ID

400

Bad Request

See detailed description below

None

403

Forbidden

The requested project does not exist im the authenticated account

None

Returns HTTP 400 if:

  1. Required 'language' parameter missing

  2. The 'path-separator' parameter can be specified only for any formats other than 'structured-json' or 'structured-yaml'

  3. Passed language is completely unrecognizable by Smartcat

  4. Passed language is neither a source language nor one of target languages

  5. Any passed label is empty

  6. The 'completion-state' value is invalid. Allowed values are: 'final', 'intermediate', 'draft'.

  7. The 'format' value is invalid. Allowed values are: 'json', 'structured-json', 'yaml', 'structured-yaml', 'ios-strings', 'android-xml'.

  8. 'fallback-to-default-language', 'export-incomplete-as-blank' or 'skip-incomplete-keys' are specified at the same time. Choose one option.

File path template

output-file-path-template - Output file path template.

Specifies how the output files should be named and located. You can use the {LANGUAGE} and {LABEL:PREFIX} placeholders to customize the output.

The ability to specify {LABEL:PREFIX} placeholder allows you to export keys that have the PREFIX value of label prefix and use the label suffix to determine the file name.

For example:

Segment A has a label file:main.json Segment B has a label file:errors.json

Specifying "resources/{LABEL:file}" as the path template and JSON as the export format would result in a ZIP file with the following structure:

resources/ main.json -> this file contains segment A errors.json -> this file contains segment B

Defaults:

  1. strings-{LANGUAGE}.json for "json" file format

  2. strings-{LANGUAGE}.yaml for "yaml" file format

  3. {LOCALE:IOS}.lproj/values.strings for "ios-strings" file format

  4. src/main/res/values-{LOCALE:ANDROID}/strings.xml for "android-xml" file format

Get Export Result

GET /api/integration/v1/document/export/{exportId}` HTTP/1.1

Accept: text/plain

GET /api/integration/v1/document/export/{exportId}

Returns export result file.

Responses

Status

Meaning

Description

Schema

200

OK

Request has been successfully completed

Returns export result file — single file if export started with one target language, zip archive otherwise

204

No Content

Export is not available yet

None

Add New Target Languages

POST /api/integration/v1/project/{projectId}/software-localization/targets` HTTP/1.1

Accept: text/plain

POST /api/integration/v1/project/{projectId}/software-localization/targets

Adds target langauges to the software localization project. If any of the specified target languages doesn't exist in the project, it will be created, but not added as a target to any existing collections. If any of the specified languages doesn't exist in the collection (the target collection existed before), it will be added as a target to the collection.

Parameters

Name

In

Type

Required

Description

target-languages

query

string

true

Comma-separated list of target languages to add. See the list of language codeshere.

Status

Meaning

Description

Schema

200

OK

Request has been successfully completed

None

400

Bad Request

Bad request

None

Returns HTTP 400 if:

  1. The list of languages is empty

  2. Any one of the language codes is incorrect

As Smartcat offers similar import/export functionality via its REST API (more on that below), you can also use curl or equivalent tools readily available in your operating system, to do basic automation tasks without installing Smartcat CLI. This may be a preferred option in organizations that have strict security requirements.

Below is an example of a Shell script that uses curl and zip to export keys from Smartcat:

#!/bin/sh

auth="Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="

task=$(curl --silent --location --request POST 'https://smartcat.com/api/integration/v1/project/446dfcf0-e699-4c91-a7ee-40e1237a9/export' \

--header "$auth" --header 'Content-Type: application/json' --data-raw '{

"languages": ["es", "zh-Hans"]

}' | tr -d '"')

echo "Export task ID: $task"

sleep 2 # wait till export is done

curl --silent --location --request GET "https://smartcat.com/api/integration/v1/document/export/"$task --header "$auth" -o product-a.zip

unzip product-a.zip

Smartcat supports two way of handling plurals:

  1. Natively (as independent segments in the editor)

  2. Via ICU MessageFormat syntax

When you open a collection of keys in the editor, you can add new keys, and when you do so, specify if the key needs to be created with all plural forms. When exporting keys, plural forms will be converted into an ICU MessageFormat-compatible string.

When importing a LocJSON file, you can specify if keys containing ICU MessageFormat syntax should be parsed and converted into individual segments in Smartcat, or kept as is (so that you can edit the raw string.

In case of raw ICU MessageFormat strings, you can plug in an interactive previewer/validator for this format.