Repository: learningequality/kolibri

Issue:
Login page remains in English even though portal is set to French
## Summary

The portal has been set to French language, and once you are logged in everything is indeed in French. However the login page remains in English, which is a barrier to DRC users.

## System information

*Please specify the Kolibri version you were using and your operating system!*

 - Version: Vodafone 0.3 pex
 - Operating system: Ubuntu 14.04
 - Browser: Firefox and IE

## Traceback or relevant snippet from server.log or browser console


## How to reproduce

1. ./kolibri language setdefault fr-fr
1. kolibri start
1. access Kolibri  via browser

## Screenshots


## Real-life consequences (anything community should be aware of, for instance how it affects your deployment)

Barrier to DRC launch


Discussion:
Hi @Kevsy, can you attach your pex file here so we can try it out on our side?
@Kevsy never mind, we can replicate this with the production server! https://fr.instantschools.learningequality.org/user#/signin
Cheers @aronasorman , much appreciated

@rtibbles I see why. The locale folders for the external paths aren't added to `LOCALE_PATHS`:

```
>>> settings.LOCALE_PATHS
[u'/Users/aron/.pex/install/kolibri-0.3.0-py2.py3-none-any.whl.cb9c5d381ba3b0738cc8fe7f8af91e21708a8552/kolibri-0.3.0-py2.py3-none-any.whl/kolibri/locale']
```

@rtibbles are those supposed to get added automatically during run time?
There's this function in `hooks.py`:

```
    @property
    def locale_data_folder(self):
        if self._module_path.startswith('kolibri.'):
            return os.path.join(getattr(django_settings, 'LOCALE_PATHS')[0], 'en', 'LC_FRONTEND_MESSAGES')
        # Is an external plugin, do otherwise!
        else:
            return os.path.join(
                os.path.dirname(self._build_path),
                getattr(self, 'locale_path', 'locale'), 'en', 'LC_FRONTEND_MESSAGES')
```
Looks like it's used by `webpack_bundle_data`. I'll try to see how this function is used.
@rtibbles ah, so Django does automatically add catalog files for external apps. But it looks for mo or po files specifically:

https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#how-django-discovers-translations

So we have to roll our own solution for frontend catalog files.
i.e. they're not added to `LOCALE_PATHS`. So we'll need another function to add those manually.
A quick function to derive the locale folders from external plugins, and:
![screen shot 2017-03-27 at 17 14 43](https://cloud.githubusercontent.com/assets/191955/24383295/f2c6803c-1310-11e7-90a4-a9b9ee4175f3.png)

I'll make a PR with my changes.


Resolving patch:
diff --git a/kolibri/deployment/default/settings/base.py b/kolibri/deployment/default/settings/base.py
--- a/kolibri/deployment/default/settings/base.py
+++ b/kolibri/deployment/default/settings/base.py
@@ -17,8 +17,9 @@
 
 # import kolibri, so we can get the path to the module.
 import kolibri
+# we load other utilities related to i18n
 # This is essential! We load the kolibri conf INSIDE the Django conf
-from kolibri.utils import conf
+from kolibri.utils import conf, i18n
 
 KOLIBRI_MODULE_PATH = os.path.dirname(kolibri.__file__)
 
@@ -64,6 +65,13 @@
     'django_js_reverse',
 ] + conf.config['INSTALLED_APPS']
 
+# Add in the external plugins' locale paths. Our frontend messages depends
+# specifically on the value of LOCALE_PATHS to find its catalog files.
+LOCALE_PATHS += [
+    i18n.get_installed_app_locale_path(app) for app in INSTALLED_APPS
+    if i18n.is_external_plugin(app)
+]
+
 MIDDLEWARE_CLASSES = (
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
diff --git a/kolibri/utils/i18n.py b/kolibri/utils/i18n.py
new file mode 100644
--- /dev/null
+++ b/kolibri/utils/i18n.py
@@ -0,0 +1,30 @@
+import importlib
+import os
+
+EXTERNAL_PLUGINS_PREFIX = "kolibri_"
+
+
+def is_external_plugin(appname):
+    '''
+    Returns true when the given app is an external plugin.
+
+    Implementation note: does a simple check on the name to see if it's
+    prefixed with "kolibri_". If so, we think it's a plugin.
+    '''
+
+    return appname.startswith(EXTERNAL_PLUGINS_PREFIX)
+
+
+def get_installed_app_locale_path(appname):
+    """
+    Load the app given by appname and return its locale folder path, if it exists.
+
+    Note that the module is imported to determine its location.
+    """
+
+    m = importlib.import_module(appname)
+    module_path = os.path.dirname(m.__file__)
+    module_locale_path = os.path.join(module_path, "locale")
+
+    if os.path.isdir(module_locale_path):
+        return module_locale_path


Test patch: