From 56da553632e4d98e0b7368ee0e380150c4efb11e Mon Sep 17 00:00:00 2001 From: Max Inno Date: Mon, 2 Feb 2026 08:14:58 +0200 Subject: [PATCH 1/2] feat: add Translation Import API support --- .../api_resources/translations/resource.py | 66 +++++++++++++++++ .../tests/test_translations_resources.py | 70 +++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/crowdin_api/api_resources/translations/resource.py b/crowdin_api/api_resources/translations/resource.py index 49fa6c0..5052d41 100644 --- a/crowdin_api/api_resources/translations/resource.py +++ b/crowdin_api/api_resources/translations/resource.py @@ -458,3 +458,69 @@ def export_project_translation( "exportApprovedOnly": exportApprovedOnly, }, ) + + def import_translations( + self, + project_id: int, + storage_id: int, + language_ids: Optional[Iterable[int]] = None, + file_id: Optional[int] = None, + import_eq_suggestions: Optional[bool] = None, + auto_approve_imported: Optional[bool] = None, + translate_hidden: Optional[bool] = None, + add_to_tm: Optional[bool] = None, + ): + """ + Import Translations + + Link to documentation: + https://support.crowdin.com/developer/api/v2/#tag/Translations/operation/api.projects.translations.exports.post + """ + + return self.requester.request( + method="post", + path=f"projects/{project_id}/translations/imports", + request_data={ + "storageId": storage_id, + "languageIds": language_ids, + "fileId": file_id, + "importEqSuggestions": import_eq_suggestions, + "autoApproveImported": auto_approve_imported, + "translateHidden": translate_hidden, + "addToTm": add_to_tm, + } + ) + + def import_translations_status( + self, + project_id: int, + import_translation_id: int + ): + """ + Import Translations Status + + Link to documentation: + https://support.crowdin.com/developer/api/v2/#tag/Translations/operation/api.projects.translations.imports.get + """ + + return self.requester.request( + method="get", + path=f"projects/{project_id}/translations/imports/{import_translation_id}", + ) + + def import_translations_report( + self, + project_id: int, + import_translation_id: int, + ): + """ + Import Translations Report + + Link to documentation: + https://support.crowdin.com/developer/api/v2/#tag/Translations/operation/api.projects.translations.imports.report.get + """ + + return self.requester.request( + method="get", + path=f"projects/{project_id}/translations/imports/{import_translation_id}/report", + ) diff --git a/crowdin_api/api_resources/translations/tests/test_translations_resources.py b/crowdin_api/api_resources/translations/tests/test_translations_resources.py index 88a73a8..faa83ca 100644 --- a/crowdin_api/api_resources/translations/tests/test_translations_resources.py +++ b/crowdin_api/api_resources/translations/tests/test_translations_resources.py @@ -632,3 +632,73 @@ def test_export_project_translation(self, m_request, in_params, request_data, ba request_data=request_data, path="projects/1/translations/exports", ) + + @pytest.mark.parametrize( + "in_data, request_data", + ( + ( + { + "storage_id": 1, + "language_ids": [1, 2, 3], + "file_id": 1, + "import_eq_suggestions": True, + "auto_approve_imported": True, + "translate_hidden": True, + "add_to_tm": True + }, + { + "storageId": 1, + "languageIds": [1, 2, 3], + "fileId": 1, + "importEqSuggestions": True, + "autoApproveImported": True, + "translateHidden": True, + "addToTm": True + }, + ), + ) + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_import_translations(self, m_request, in_data, request_data, base_absolut_url): + m_request.return_value = "response" + + project_id = 1 + + resource = self.get_resource(base_absolut_url) + assert resource.import_translations(project_id, **in_data) == "response" + + m_request.assert_called_once_with( + method="post", + path=f"projects/{project_id}/translations/imports", + request_data=request_data, + ) + + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_import_translations_status(self, m_request, base_absolut_url): + m_request.return_value = "response" + + project_id = 1 + import_translation_id = 2 + + resource = self.get_resource(base_absolut_url) + assert resource.import_translations_status(project_id, import_translation_id) == "response" + + m_request.assert_called_once_with( + method="get", + path=f"projects/{project_id}/translations/imports/{import_translation_id}", + ) + + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_import_translations_report(self, m_request, base_absolut_url): + m_request.return_value = "response" + + project_id = 1 + import_translation_id = 2 + + resource = self.get_resource(base_absolut_url) + assert resource.import_translations_report(project_id, import_translation_id) == "response" + + m_request.assert_called_once_with( + method="get", + path=f"projects/{project_id}/translations/imports/{import_translation_id}/report", + ) From ecd9d4f46e52d8e4bbb26fd038d25278e57bca4d Mon Sep 17 00:00:00 2001 From: Andrii Bodnar Date: Mon, 2 Feb 2026 10:52:22 +0200 Subject: [PATCH 2/2] Update crowdin_api/api_resources/translations/resource.py --- crowdin_api/api_resources/translations/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowdin_api/api_resources/translations/resource.py b/crowdin_api/api_resources/translations/resource.py index 5052d41..cefe2e3 100644 --- a/crowdin_api/api_resources/translations/resource.py +++ b/crowdin_api/api_resources/translations/resource.py @@ -474,7 +474,7 @@ def import_translations( Import Translations Link to documentation: - https://support.crowdin.com/developer/api/v2/#tag/Translations/operation/api.projects.translations.exports.post + https://support.crowdin.com/developer/api/v2/#tag/Translations/operation/api.projects.translations.imports """ return self.requester.request(