Repository: akvo/akvo-rsr

Issue:
Add translations
We should add translations back into RSR v3:
- [x] Mark all strings as translatable
- [x] Translate strings
  - @lauraroverts manages this, French and Spanish will be done by May 22nd
- [x] UI for selecting a language  (@loicsans?)
- [x] Implement translations into RSR
- [x] Configure Nginx to not rewrite supported languages
## Test plan

GIVEN all RSR pages
WHEN viewing the page
THEN a language selector is present in the project header

GIVEN that RSR is displayed in a language
WHEN viewing the language selector
THEN this language should be indicated by a flag
AND this language should not appear in the dropdown list

GIVEN the language selector
WHEN a language is switched
THEN the user should stay on the same page
AND the page should be shown in the selected language

GIVEN the three unsupported languages (ru, nl, de)
WHEN the user tries to visit those (e.g. through /ru/projects/)
THEN the user should be redirected to the English version



Discussion:
Spanish and French translations in Transifex are ready to be published


Resolving patch:
diff --git a/akvo/rsr/views/account.py b/akvo/rsr/views/account.py
--- a/akvo/rsr/views/account.py
+++ b/akvo/rsr/views/account.py
@@ -19,7 +19,7 @@
 from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
 from django.http import (HttpResponse, HttpResponseRedirect,
                          HttpResponseForbidden)
-from django.shortcuts import render_to_response
+from django.shortcuts import render_to_response, redirect
 from django.template import RequestContext
 
 from registration.models import RegistrationProfile
@@ -102,7 +102,7 @@ def sign_in(request):
         if form.is_valid():
             login(request, form.get_user())
             next_page = request.GET.get('next')
-            return HttpResponseRedirect(next_page) if next_page else HttpResponseRedirect('/myrsr')
+            return HttpResponseRedirect(next_page) if next_page else redirect('my_details')
     # Password reset on sign in page
     elif request.method == "POST" and 'email' in request.POST:
         reset_form = PasswordResetForm(data=request.POST)
@@ -116,7 +116,7 @@ def sign_in(request):
 def sign_out(request):
     """Log out resouce."""
     logout(request)
-    return HttpResponseRedirect('/')
+    return redirect('index')
 
 
 def api_key_xml_response(user, orgs):
diff --git a/akvo/urls.py b/akvo/urls.py
--- a/akvo/urls.py
+++ b/akvo/urls.py
@@ -17,12 +17,17 @@
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
+from django.conf.urls.i18n import i18n_patterns
 
 from paypal.standard.ipn.views import ipn as paypal_ipn
 
 admin.autodiscover()
 
-urlpatterns = patterns(
+####################################################################################
+### Internationalisation URLs                                                    ###
+####################################################################################
+
+urlpatterns = i18n_patterns(
     '',
 
     # Home page
@@ -42,9 +47,6 @@
     url(r'^project/(?P<project_id>\d+)/report/$',
         'akvo.rsr.views.project.report', name='project-report'),
 
-    url(r'^project/(?P<project_id>\d+)/iati/$',
-        'akvo.rsr.views.project.iati', name='project-iati'),
-
     url(r'^project/(?P<project_id>\d+)/widgets/$',
         'akvo.rsr.views.project.widgets', name='project-widgets'),
 
@@ -149,11 +151,44 @@
 
     # Admin
     (r'^admin/', include(admin.site.urls)),
+)
+
+####################################################################################
+### Non-internationalisation URLs                                                ###
+####################################################################################
+
+urlpatterns += patterns(
+    '',
+
+    # IATI file
+    url(r'^project/(?P<project_id>\d+)/iati/$',
+        'akvo.rsr.views.project.iati', name='project-iati'),
+
+    # TastyPie API
+    (r'^api/', include(named_api('v1').urls)),
 
     # Django Rest Framework urls
     (r'^rest/v1/', include('akvo.rest.urls')),
     url(r'^rest/docs/', include('rest_framework_swagger.urls')),
 
+    # RSS
+    url(r'^rss/updates/(?P<project_id>\d+)/$',
+        ProjectUpdates(),
+        name="rss_project_updates"),
+
+    url(r'^rss/org-updates/(?P<org_id>\d+)/$',
+        OrganisationUpdates(),
+        name="rss_org_updates"),
+
+    url(r'^rss/all-updates/$',
+        AllProjectUpdates(),
+        name="rss_all_updates"),
+
+    # Auth token for mobile apps
+    url(r'^auth/token/$',
+        'akvo.rsr.views.account.api_key',
+        name="auth_token"),
+
     # Widgets
     url(r'^widgets/projects/map/$',
         widget_views.ProjectMapView.as_view(),
@@ -186,31 +221,6 @@
     url(r'^widgets/project-small/random/$',
         widget_views.RandomProjectSmallView.as_view(),
         name="widget_random_project_small"),
-
-    # RSS
-    url(r'^rss/updates/(?P<project_id>\d+)/$',
-        ProjectUpdates(),
-        name="rss_project_updates"),
-
-    url(r'^rss/org-updates/(?P<org_id>\d+)/$',
-        OrganisationUpdates(),
-        name="rss_org_updates"),
-
-    url(r'^rss/all-updates/$',
-        AllProjectUpdates(),
-        name="rss_all_updates"),
-
-    # Auth token for mobile apps
-    url(r'^auth/token/$',
-        'akvo.rsr.views.account.api_key',
-        name="auth_token"),
-
-)
-
-# TastyPie API
-urlpatterns += patterns(
-    '',
-    (r'^api/', include(named_api('v1').urls)),
 )
 
 


Test patch: