Repository: learningequality/kolibri

Issue:
add device setting for changing default language

The default language for a device is now configurable during setup. However there is currently no UI for modifying this after the fact.

Needs design - cc @khangmach @jtamiace 





Discussion:
@indirectlylit there is a "change language" option within the user dropdown
The user dropdown updates the language for the current user.

This issue is for the device default, which is set up during initial onboarding. This affects the default language for newly-created users.

It also affects the language of the sign-in screen. Will probably need to be added to device settings somewhere:

![image](https://user-images.githubusercontent.com/2367265/30794590-f2f03796-a17d-11e7-9d04-98df7b1fdf2c.png)

![device setting](https://user-images.githubusercontent.com/6668144/31142351-e8acad02-a82e-11e7-9833-8b1cf828c253.png)

Putting this here so that it doesn't get lost. Still prefer the option on the left, with tab name of "Settings" to minimize the number of tabs in the future "Data" & "Facilities"

Note from @indirectlylit in Slack:

> (minor subtlety is the other language switchers change the global language immediately, whereas this one wouldn’t because the admin’s language preference still takes priority. doesn’t really affect the designs above, just an interaction detail)


![slice](https://user-images.githubusercontent.com/6668144/31144062-560641a6-a834-11e7-8b19-74754e46d61c.png)

I think we like this one better. In the words of Devon:

> "simple drop-down is simple"

This will require some new additions to the code:

1. A Viewset to be able to modify the default language in the DeviceSettings model
1. An entirely new section for Device > Settings

Resolving patch:
diff --git a/kolibri/core/device/api.py b/kolibri/core/device/api.py
--- a/kolibri/core/device/api.py
+++ b/kolibri/core/device/api.py
@@ -1,5 +1,7 @@
 from django.conf import settings
 from django.utils.decorators import method_decorator
+from django.utils.translation import check_for_language
+from django.http.response import HttpResponseBadRequest
 from morango.models import InstanceIDModel
 from rest_framework import mixins
 from rest_framework import status
@@ -9,6 +11,7 @@
 
 import kolibri
 from .models import DevicePermissions
+from .models import DeviceSettings
 from .permissions import NotProvisionedCanPost
 from .permissions import UserHasAnyDevicePermissions
 from .serializers import DevicePermissionsSerializer
@@ -99,3 +102,32 @@ def get(self, request, format=None):
         info['installer'] = installation_type()
 
         return Response(info)
+
+
+class DeviceLanguageSettingViewset(views.APIView):
+
+    permission_classes = (UserHasAnyDevicePermissions, )
+
+    def get(self, request):
+        settings = DeviceSettings.objects.get()
+        return Response({
+            'language_id': settings.language_id
+        })
+
+    def patch(self, request):
+        settings = DeviceSettings.objects.get()
+
+        try:
+            request_lang = request.data.get('language_id', '')
+        except AttributeError:
+            return HttpResponseBadRequest('Value must be a JSON object with "language_id" field: {}'.format(request.data))
+
+        if request_lang == '':
+            return HttpResponseBadRequest('"language_id" is required')
+
+        if request_lang is None or check_for_language(request_lang):
+            settings.language_id = request_lang
+            settings.save()
+            return self.get(request)
+        else:
+            return HttpResponseBadRequest('Unknown language: {}'.format(request_lang))
diff --git a/kolibri/core/device/api_urls.py b/kolibri/core/device/api_urls.py
--- a/kolibri/core/device/api_urls.py
+++ b/kolibri/core/device/api_urls.py
@@ -6,6 +6,7 @@
 from .api import DevicePermissionsViewSet
 from .api import DeviceProvisionView
 from .api import FreeSpaceView
+from .api import DeviceLanguageSettingViewset
 
 router = routers.SimpleRouter()
 router.register(r'devicepermissions', DevicePermissionsViewSet, base_name='devicepermissions')
@@ -15,4 +16,5 @@
     url(r'^deviceprovision/', DeviceProvisionView.as_view({'post': 'create'}), name='deviceprovision'),
     url(r'^freespace/', FreeSpaceView.as_view({'get': 'list'}), name='freespace'),
     url(r'^deviceinfo/', DeviceInfoView.as_view(), name='deviceinfo'),
+    url(r'^devicelanguage/', DeviceLanguageSettingViewset.as_view(), name='devicelanguage'),
 ]


Test patch: