Custom Bundle Generator Module
Use this module to support custom formats of Target File Bundles. The generation process is delegated to your Crowdin app that implements a custom bundle generator module. When translations are ready, Crowdin sends the translation data to your app, which returns the generated bundle in the desired format.
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", "multilingualExport": true, "stringsExport": true, "extensions": [ ".resx" ] } ] }}
Properties
key | Type: Required: yes Description: Module identifier within the Crowdin app. |
type | Type: Required: yes Description: Identifier of the custom bundle type. Can be used in the API to trigger the processing of this module when generating translation bundles. |
url | Type: Required: yes Description: The relative URL triggered during translation export. Crowdin sends a request to this URL to initiate custom bundle generation. |
multilingualExport | Type: Required: no Allowed values: Description: Enables export of strings for multiple target languages in a single request. Useful for file formats that support multiple languages within the same bundle. |
stringsExport | Type: Required: yes Description: Must be set to |
extensions | Type: Required: yes Description: List of file extensions associated with the generated bundles (e.g., |
Communication between Custom Bundle Generator App and Crowdin
When a user requests a translation bundle export, Crowdin sends an HTTP request to the app’s configured URL ($baseUrl . $url
) with the necessary project, language, and translation data. The app processes the data and responds with the generated bundle file.
The requests and responses to and from the custom bundle generator 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": "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" }, "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 } ], "strings": [...], // array of segments "stringsUrl": "https://tmp.downloads.crowdin.com/strings.ndjson" // 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. Always set to |
strings , stringsUrl | Type(strings): Type(stringsUrl): Description: Contains the translation strings for the bundle generation. Either |
Expected Response from the App
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: Use either The format of the file depends on your implementation. |
error.message | Type: Description: An error message that can be passed from the app to Crowdin and will be visible to a user in the UI. |
Translation Strings Structure
Below is an example of the structure used to pass translation strings to the app for custom bundle generation.
Payload example:
// strings should be in "new-line delimited json" format if they passed by URL[ { // non plural string "id": 1, // numeric identifier of the string in Crowdin "identifier": "string-key-1", // required: unique string key "context": "Some context", // optional: additional info for translators "customData": "max 4 KB of custom data", // optional: preserved on export "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: source content "translations": { // required: grouped by target language ID "uk": { // targetLanguage.id "text": "Переклад стрічки", // required: translation text "status": "untranslated | translated | approved" // optional, default "translated" }, // can be other languages for multilingual, check "targetLanguages" in the request payload } }, { // plural string "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:
id | Type: Required: yes Description: Numeric identifier of the string in your Crowdin project. Required for mapping translations. |
identifier | Type: Required: yes Description: Unique string key within the file. Required. |
text | Type: Description: Source string text. Required for generating translations. For plural strings, this is an object with plural form keys from |
customData | Type: Required: no Description: Any custom data that needs to be linked to the string. Added custom data will be exported along the corresponding strings on translation export. |
translations | Type: Required: yes Description: Required translations for each target language. Each language ID maps to an object with a |