Custom File Format Module
Use this module to add support of new custom file formats. It’s implemented by delegating a source file parsing to an app with a custom file format module. When translations are completed, Crowdin passes a source file and a string array with translations to the Custom file format app for translation files generation.
Access
You can grant access to this module to one of the following user categories:
For Crowdin:
- Only me (i.e., project owner)
- All project members
- Selected users
For Crowdin Enterprise:
- Only organization admins
- All users in the organization projects
- Selected users
Structure
{ "modules": { "custom-file-format": [ { "key": "your-module-key-type-xyz", "type": "type-xyz", "url": "/process", "multilingual": true, "signaturePatterns": { "fileName": "^.+\\.xyz$", "fileContent": "<properties>\\s*<property\\s+name=.*value=.*/>" } } ] }}
Properties
key | Type: Required: yes Description: Module identifier within the Crowdin app. |
type | Type: Required: yes Description: The custom file format identifier. Can be used in API to force the processing of the files by the Custom file format app. If the |
url | Type: Required: yes Description: The relative URL triggered on file import, update, translation upload, and export. |
multilingual | Type: Required: no Allowed values: Description: This parameter is used to combine the content of multiple languages into one request when uploading and downloading translations in your Crowdin project. |
signaturePatterns | Type: Description: Contains |
Communication between Custom File Format App and Crowdin
On the initial file import, the system detects custom file format using the signaturePatterns
or type
parameters and makes an HTTP request to the app’s URL ($baseUrl . $url
) for further processing. Then app processes the file in a custom format and responds to the system. The requests and responses to and from the custom file format apps have two-minute timeouts. The maximum request and response payload size is limited to 5 MB.
Request to the App
Request payload example:
// max request payload - 5 MB// wait timeout - 2 minutes{ "jobType": "parse-file | build-file", "organization": { "id": 1, "domain": "{domain}", "baseUrl": "https://{domain}.crowdin.com", "apiBaseUrl": "https://{domain}.api.crowdin.com" }, "project": { "id": 1, "identifier": "your-project-identifier", "name": "Your Project Name" }, "file": { "id": 1, "name": "file.xml", "content": "VGhpcyBpcyBmaWxlIGNvbnRlbnQ=", // base64 encoded source file content "contentUrl": "https://crowdin-tmp.downloads.crowdin.com/1/file.xml?aws-signature=..." // source file public URL }, "sourceLanguage": { "id": "es", "name": "Spanish", "editorCode": "es", "twoLettersCode": "es", "threeLettersCode": "spa", "locale": "es-ES", "androidCode": "es-rES", "osxCode": "es.lproj", "osxLocale": "es", "pluralCategoryNames": ["one"], "pluralRules": "(n != 1)" }, "targetLanguages": [ { // same structure as for sourceLanguage, empty when uploading a new source file, one element for import_translations & export, can be more for multilingual files } ], "strings": [...], // for the build-file jobs, array of segments "stringsUrl": "https://tmp.downloads.crowdin.com/strings.ndjson" // for the build-file jobs, file with segments, in new-line delimited json format}
Properties:
jobType | Type: Possible values: Description: Specifies the action that should be executed by the app. |
file.content , file.contentUrl | Type: Description: Parameters used to pass the base64 encoded source file content ( |
strings , stringsUrl | Type(strings): Type(stringsUrl): Description: Parameters used for translations download (for |
Expected Response from the App for the parse-file Job Type
Response payload example:
// max response payload - 5 MB// wait timeout - 2 minutes{ "data": { "strings": [...], // segments array "stringsUrl": "https://app.example.com/jKe8ujs7a-segments.ndjson", // new-line delimited json file with parsed strings "preview": "VGhpbmdzIGFyZSBvbmx5IGltcG9zc2libGUgdW50aWwgdGhleSdyZSBub3Qu", // optional, base64 encoded content of preview html file, not supported if there are plural strings "previewUrl": "https://app.example.com/LN3km2K6M-preview.html", // optional, URL of preview html file, not supported if there are plural strings }, "error": { "message": "Your error message" }}
Properties:
data.strings , data.stringsUrl | Type(data.strings): Type(data.stringsUrl): Description: Parameters used to pass the parsed strings content. |
preview , previewUrl | Type(preview): Type(previewUrl): Description: Parameters used to pass the optional HTML preview of the parsed strings content, which can be generated by the app. The generated HTML preview will be displayed in the Editor. See the HTML Preview file example. |
error.message | Type: Description: An error message that can be passed from the app to Crowdin Enterprise and will be visible to a user in the UI. |
Expected Response from the App for the build-file Job Type
Response payload example:
// max response payload - 5 MB// wait timeout - 2 minutes{ "data": { "content": "TWF5IHRoZSBGb3JjZSBiZSB3aXRoIHlvdS4=", // base64 encoded translation file content "contentUrl": "https://app.example.com/p5uLEpq8p-result.xml", // translation file public URL }, "error": { "message": "Your error message" }}
Properties:
data.content , data.contentUrl | Type(data.content): Type(data.contentUrl): Description: Parameters used to pass the base64 encoded translation file content ( |
error.message | Type: Description: An error message that can be passed from the app to Crowdin Enterprise and will be visible to a user in the UI. |
Strings Array Structure
Below you can see an example of the strings structure expected from the app for parse-file
job type and passed to the app for build-file
job type.
Payload example:
// strings should be in "new-line delimited json" format if they passed by URL[ { // non plural string "previewId": 1, // only for "parse-file" jobType, required when the HTML preview of the file is generated "id": 1, // only for "build-file" jobType "identifier": "string-key-1", // required "context": "Some context", // optional "customData": "max 4 KB of custom data", // optional "maxLength": 10, // optional, default null "isHidden": false, // optional, default null "hasPlurals": false, // optional, default false "labels": ["label-one", "label-two"], // optional, default [] "text": "String source text", // required "translations": { // optional "uk": { // targetLanguage.id "text": "Переклад стрічки", // required "status": "untranslated | translated | approved" // optional, default "translated" }, // can be other languages for multilingual, check "targetLanguages" in the request payload } }, { // plural string "previewId": 2, "id": 2, "identifier": "string-key-2", "context": "Some optional context", "customData": "max 4 KB of custom data", "maxLength": 15, "isHidden": false, "hasPlurals": true, "labels": [], "text": { // keys from sourceLanguage.pluralCategoryNames "one": "One file", "other": "%d files", }, "translations": { "uk": { "text": { // keys from targetLanguage.pluralCategoryNames "one": "One file", "few": "%d файла", "many": "%d файлів", }, "status": { "one": "untranslated", "few": "translated", "many": "approved", } } } }]
Properties:
previewId | Type: Required: yes (only for the Description: Numeric identifier of the string in the HTML Preview file. Used for |
id | Type: Description: Numeric identifier of the string in your Crowdin Enterprise project. Used for |
identifier | Type: Description: Unique string key within the file. |
customData | Type: Description: Any custom data that need to be linked to the string. Added custom data will be exported along the corresponding strings on translation export. |
HTML Preview of the File
HTML Preview of the file example:
<html lang="en"> <head> <title>Optional Title</title> <style> table, th, td { border: 1px solid #aaa; } </style> </head> <body> <h1 style="text-align: center">HTML preview of the file</h1> <table style="width: 100%"> <tr> <th>Key:</th> <th>Text:</th> </tr> <tr> <td>Key 1</td> <td><span id="string_preview_id_1">Source Text 1</span></td> <!-- 1 is previewId in strings json --> </tr> <tr> <td>Key 2</td> <td><span id="string_preview_id_2">Source Text 2</span></td> <!-- 2 is previewId in strings json --> </tr> </table> </body></html>