Repository: WeblateOrg/weblate

Issue:
Create project in api missing source language
Hi i want to create project from component and i need to set up source_language.
I read the document and saw that i need only free field name,slug and web.
When i created project is saw weblate response for me that source_language en and checked it on the web interface.
I tryied to send "source_language" in the reqest i created project but had the same result.

```
curl -H 'Content-Type: application/json' -H "Authorization: Token ${api_token}" --data-binary "{\"name\":\"${job_name}\", \"slug\":\"${job_name}\",\"web\":\"https://exaple.com\","source_language\":{\"code\":\"ru\",\"name\":\"Russian\",\"direction\":\"ltr\",\"web_url\":\"http://weblate.exaple.com/languages/ru/\",\"url\":\"http://weblate.exaple.com/api/languages/ru/\"}}" https://weblate.exaple.com/api/projects/`
```

```
{
  "name": "master_locales",
  "slug": "master_locales",
  "web": "https://example.site",
  "source_language": {
    "code": "en",
    "name": "English",
    "direction": "ltr",
    "web_url": "http:/example.site/languages/en/",
    "url": "http://example.site/api/languages/en/"
  },
  "web_url": "http://example.site/projects/master_locales/",
  "url": "http://example.site/api/projects/master_locales/",
  "components_list_url": "http://example.site/api/projects/master_locales/components/",
  "repository_url": "http://example.site/api/projects/master_locales/repository/",
  "statistics_url": "http://example.site/api/projects/master_locales/statistics/",
  "changes_list_url": "http://example.site/api/projects/master_locales/changes/",
  "languages_url": "http://example.site/api/projects/master_locales/languages/"
}
```
One more problem when i creater component, the File_format: JSON nested structure file didn't install in the property.
In our workflow we need to use all api featuries.

<bountysource-plugin>

---
Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/87440949-create-project-in-api-missing-source-language?utm_campaign=plugin&utm_content=tracker%2F253393&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F253393&utm_medium=issues&utm_source=github).
</bountysource-plugin>


Discussion:
Configuring source language is currently missing from the API.

I didn't get what was your problem with nested JSON, can you please open separate issue describing that? Mixing unrelated topics in single issue makes it hard to properly track then.
About "Configuring source language",will you fix it?
About json_nested it's my mistake it's working, sorry.

It will get eventually fixed, currently it's not on the roadmap.

Resolving patch:
diff --git a/weblate/api/serializers.py b/weblate/api/serializers.py
--- a/weblate/api/serializers.py
+++ b/weblate/api/serializers.py
@@ -85,13 +85,29 @@ class Meta:
         model = Language
         fields = ("code", "name", "direction", "web_url", "url")
         extra_kwargs = {
-            "url": {"view_name": "api:language-detail", "lookup_field": "code"}
+            "url": {"view_name": "api:language-detail", "lookup_field": "code"},
+            "code": {"validators": []},
         }
 
+    def validate_code(self, value):
+        check_query = Language.objects.filter(code=value)
+        if check_query.exists() and not (
+            isinstance(self.parent, ProjectSerializer)
+            and self.field_name == "source_language"
+        ):
+            raise serializers.ValidationError(
+                "Language with this Language code already exists."
+            )
+        if not check_query.exists():
+            raise serializers.ValidationError(
+                "Language with this language code was not found."
+            )
+        return value
+
 
 class ProjectSerializer(serializers.ModelSerializer):
     web_url = AbsoluteURLField(source="get_absolute_url", read_only=True)
-    source_language = LanguageSerializer(read_only=True)
+    source_language = LanguageSerializer(required=False)
     components_list_url = serializers.HyperlinkedIdentityField(
         view_name="api:project-components", lookup_field="slug"
     )
@@ -127,6 +143,15 @@ class Meta:
             "url": {"view_name": "api:project-detail", "lookup_field": "slug"}
         }
 
+    def create(self, validated_data):
+        source_language_validated = validated_data.get("source_language")
+        if source_language_validated:
+            validated_data["source_language"] = Language.objects.get(
+                code=source_language_validated.get("code")
+            )
+        project = Project.objects.create(**validated_data)
+        return project
+
 
 class RepoField(serializers.CharField):
     def get_attribute(self, instance):


Test patch:
diff --git a/weblate/api/tests.py b/weblate/api/tests.py
--- a/weblate/api/tests.py
+++ b/weblate/api/tests.py
@@ -84,10 +84,11 @@ def do_request(
         method="get",
         request=None,
         skip=(),
+        format="multipart",
     ):
         self.authenticate(superuser)
         url = reverse(name, kwargs=kwargs)
-        response = getattr(self.client, method)(url, request)
+        response = getattr(self.client, method)(url, request, format)
         self.assertEqual(response.status_code, code)
         if data is not None:
             for item in skip:
@@ -211,6 +212,67 @@ def test_create(self):
         )
         self.assertEqual(Project.objects.count(), 2)
 
+    def test_create_with_source_language(self):
+        self.do_request(
+            "api:project-list",
+            method="post",
+            code=403,
+            format="json",
+            request={
+                "name": "API project",
+                "slug": "api-project",
+                "web": "https://weblate.org/",
+                "source_language": {
+                    "code": "ru",
+                    "name": "Russian",
+                    "direction": "ltr",
+                },
+            },
+        )
+        response = self.do_request(
+            "api:project-list",
+            method="post",
+            code=201,
+            superuser=True,
+            format="json",
+            request={
+                "name": "API project",
+                "slug": "api-project",
+                "web": "https://weblate.org/",
+                "source_language": {
+                    "code": "ru",
+                    "name": "Russian",
+                    "direction": "ltr",
+                },
+            },
+        )
+        error_response = self.do_request(
+            "api:project-list",
+            method="post",
+            code=400,
+            superuser=True,
+            format="json",
+            request={
+                "name": "API project",
+                "slug": "api-project",
+                "web": "https://weblate.org/",
+                "source_language": {
+                    "code": "invalid",
+                    "name": "Invalid",
+                    "direction": "ltr",
+                },
+            },
+        )
+        self.assertEqual(Project.objects.count(), 2)
+        self.assertEqual(response.data["source_language"]["code"], "ru")
+        self.assertEqual(
+            Project.objects.get(slug="api-project").source_language.code, "ru"
+        )
+        self.assertEqual(
+            error_response.data["source_language"]["code"][0],
+            "Language with this language code was not found.",
+        )
+
     def test_create_component(self):
         self.do_request(
             "api:project-components",