Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions crowdin_api/api_resources/ai/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -1315,3 +1315,29 @@ def list_supported_ai_provider_models(
path="ai/providers/supported-models",
params=params
)

def ai_translate_strings(
self,
aiId: int,
projectId: int,
targetLanguageIds,
stringIds=None,
Comment on lines +1323 to +1324
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

targetLanguageIds and stringIds are missing type hints here, while other resource methods typically annotate these as Optional[Iterable[str]] / Optional[Iterable[int]]. Adding explicit types (and making stringIds an Optional[...]) will improve IDE/autocomplete support and make the public API clearer.

Suggested change
targetLanguageIds,
stringIds=None,
targetLanguageIds: Optional[Iterable[str]],
stringIds: Optional[Iterable[int]] = None,

Copilot uses AI. Check for mistakes.
):
"""
AI Translate Strings.

Link to API docs:
https://developer.crowdin.com/api/v2/#tag/AI/operation/api.ai.translations.generate
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation link in this docstring doesn’t match the endpoint being called (ai/{aiId}/translate-strings) and also uses the non-enterprise base URL. Please update it to the correct "AI Translate Strings" operation URL for this resource (enterprise vs. non-enterprise) so readers aren’t sent to the wrong API docs.

Suggested change
https://developer.crowdin.com/api/v2/#tag/AI/operation/api.ai.translations.generate
https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.translate-strings.enterprise.generate

Copilot uses AI. Check for mistakes.
"""
post_data = {
"projectId": projectId,
"targetLanguageIds": targetLanguageIds,
}
if stringIds is not None:
post_data["stringIds"] = stringIds

return self.requester.request(
method="post",
path=f"ai/{aiId}/translate-strings",
post_data=post_data,
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APIRequester.request() does not accept a post_data keyword (it only supports request_data), so this will raise a TypeError at runtime when the request is executed. Please rename post_data to request_data here (and keep the dict as-is).

Suggested change
post_data=post_data,
request_data=post_data,

Copilot uses AI. Check for mistakes.
Comment on lines +1319 to +1342
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says this adds support for the Crowdin API "AI Translate Strings" endpoint (linked under the non-enterprise docs), but the implementation is currently only on EnterpriseAIResource and uses the enterprise-style path (no users/{userId} prefix). Please confirm whether this endpoint is enterprise-only; if it’s part of the standard API as well, the method (and tests) likely need to be added to AIResource with the correct path/params, or the PR description should be updated to reflect enterprise scope.

Copilot uses AI. Check for mistakes.
)
22 changes: 22 additions & 0 deletions crowdin_api/api_resources/ai/tests/test_ai_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2104,3 +2104,25 @@ def test_list_supported_ai_provider_models(self, m_request, in_params, request_p
path="ai/providers/supported-models",
params=request_params
)

@mock.patch("crowdin_api.requester.APIRequester.request")
def test_ai_translate_strings(self, m_request, base_absolut_url):
m_request.return_value = "response"

resource = self.get_resource(base_absolut_url)
assert resource.ai_translate_strings(
aiId=1,
projectId=42,
targetLanguageIds=["uk", "fr"],
stringIds=[101, 102],
) == "response"
Comment on lines +2112 to +2118
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation conditionally includes stringIds only when provided, but the tests only cover the case where stringIds is set. Consider adding a second assertion covering the stringIds=None/omitted case to lock in the payload behavior for that branch.

Copilot uses AI. Check for mistakes.

m_request.assert_called_once_with(
method="post",
path="ai/1/translate-strings",
post_data={
"projectId": 42,
"targetLanguageIds": ["uk", "fr"],
"stringIds": [101, 102],
},
)
Comment on lines +2120 to +2128
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test asserts the request is called with post_data=..., but APIRequester.request() uses request_data for payloads. Once the implementation is fixed to use request_data, the test should be updated accordingly so it matches the real requester API.

Copilot uses AI. Check for mistakes.