Browse Source

add lang support in endpoint,internal lib and tests

Guénaël Muller 6 years ago
parent
commit
c45953dfae

+ 6 - 0
backend/tracim_backend/lib/core/user.py View File

@@ -314,6 +314,7 @@ class UserApi(object):
314 314
             email: str=None,
315 315
             password: str=None,
316 316
             timezone: str=None,
317
+            lang: str=None,
317 318
             groups: typing.Optional[typing.List[Group]]=None,
318 319
             do_save=True,
319 320
     ) -> User:
@@ -330,6 +331,9 @@ class UserApi(object):
330 331
         if timezone is not None:
331 332
             user.timezone = timezone
332 333
 
334
+        if lang is not None:
335
+            user.lang = lang
336
+
333 337
         if groups is not None:
334 338
             # INFO - G.M - 2018-07-18 - Delete old groups
335 339
             for group in user.groups:
@@ -351,6 +355,7 @@ class UserApi(object):
351 355
         password: str = None,
352 356
         name: str = None,
353 357
         timezone: str = '',
358
+        lang: str= None,
354 359
         groups=[],
355 360
         do_save: bool=True,
356 361
         do_notify: bool=True,
@@ -362,6 +367,7 @@ class UserApi(object):
362 367
             email=email,
363 368
             password=password,
364 369
             timezone=timezone,
370
+            lang=lang,
365 371
             do_save=False,
366 372
         )
367 373
         if do_notify:

+ 8 - 1
backend/tracim_backend/models/context_models.py View File

@@ -81,9 +81,10 @@ class UserInfos(object):
81 81
     """
82 82
     Just some user infos
83 83
     """
84
-    def __init__(self, timezone: str, public_name: str) -> None:
84
+    def __init__(self, timezone: str, public_name: str, lang: str) -> None:
85 85
         self.timezone = timezone
86 86
         self.public_name = public_name
87
+        self.lang = lang
87 88
 
88 89
 
89 90
 class UserProfile(object):
@@ -105,6 +106,7 @@ class UserCreation(object):
105 106
             public_name: str = None,
106 107
             timezone: str = None,
107 108
             profile: str = None,
109
+            lang: str = None,
108 110
             email_notification: bool = True,
109 111
     ) -> None:
110 112
         self.email = email
@@ -113,6 +115,7 @@ class UserCreation(object):
113 115
         self.password = password or password_generator()
114 116
         self.public_name = public_name or None
115 117
         self.timezone = timezone or ''
118
+        self.lang = lang or None
116 119
         self.profile = profile or Group.TIM_USER_GROUPNAME
117 120
         self.email_notification = email_notification
118 121
 
@@ -407,6 +410,10 @@ class UserInContext(object):
407 410
         return self.user.timezone
408 411
 
409 412
     @property
413
+    def lang(self) -> str:
414
+        return self.user.lang
415
+
416
+    @property
410 417
     def profile(self) -> Profile:
411 418
         return self.user.profile.name
412 419
 

+ 2 - 0
backend/tracim_backend/tests/functional/test_session.py View File

@@ -160,6 +160,7 @@ class TestWhoamiEndpoint(FunctionalTest):
160 160
         assert res.json_body['profile'] == 'administrators'
161 161
         assert res.json_body['caldav_url'] is None
162 162
         assert res.json_body['avatar_url'] is None
163
+        assert res.json_body['lang'] is None
163 164
 
164 165
     def test_api__try_whoami_enpoint__err_401__user_is_not_active(self):
165 166
         dbsession = get_tm_session(self.session_factory, transaction.manager)
@@ -183,6 +184,7 @@ class TestWhoamiEndpoint(FunctionalTest):
183 184
             name='bob',
184 185
             groups=groups,
185 186
             timezone='Europe/Paris',
187
+            lang='en',
186 188
             do_save=True,
187 189
             do_notify=False,
188 190
         )

+ 81 - 2
backend/tracim_backend/tests/functional/test_user.py View File

@@ -74,6 +74,7 @@ class TestUserRecentlyActiveContentEndpoint(FunctionalTest):
74 74
             name='bob',
75 75
             groups=groups,
76 76
             timezone='Europe/Paris',
77
+            lang='fr',
77 78
             do_save=True,
78 79
             do_notify=False,
79 80
         )
@@ -198,6 +199,7 @@ class TestUserRecentlyActiveContentEndpoint(FunctionalTest):
198 199
             name='bob',
199 200
             groups=groups,
200 201
             timezone='Europe/Paris',
202
+            lang='fr',
201 203
             do_save=True,
202 204
             do_notify=False,
203 205
         )
@@ -289,6 +291,7 @@ class TestUserRecentlyActiveContentEndpoint(FunctionalTest):
289 291
             name='bob',
290 292
             groups=groups,
291 293
             timezone='Europe/Paris',
294
+            lang='fr',
292 295
             do_save=True,
293 296
             do_notify=False,
294 297
         )
@@ -414,6 +417,7 @@ class TestUserRecentlyActiveContentEndpoint(FunctionalTest):
414 417
             name='bob',
415 418
             groups=groups,
416 419
             timezone='Europe/Paris',
420
+            lang='fr',
417 421
             do_save=True,
418 422
             do_notify=False,
419 423
         )
@@ -702,6 +706,7 @@ class TestUserReadStatusEndpoint(FunctionalTest):
702 706
             name='bob',
703 707
             groups=groups,
704 708
             timezone='Europe/Paris',
709
+            lang='fr',
705 710
             do_save=True,
706 711
             do_notify=False,
707 712
         )
@@ -814,6 +819,7 @@ class TestUserReadStatusEndpoint(FunctionalTest):
814 819
             name='bob',
815 820
             groups=groups,
816 821
             timezone='Europe/Paris',
822
+            lang='fr',
817 823
             do_save=True,
818 824
             do_notify=False,
819 825
         )
@@ -937,6 +943,7 @@ class TestUserReadStatusEndpoint(FunctionalTest):
937 943
             name='bob',
938 944
             groups=groups,
939 945
             timezone='Europe/Paris',
946
+            lang='fr',
940 947
             do_save=True,
941 948
             do_notify=False,
942 949
         )
@@ -1150,6 +1157,7 @@ class TestUserSetContentAsRead(FunctionalTest):
1150 1157
             name='bob',
1151 1158
             groups=groups,
1152 1159
             timezone='Europe/Paris',
1160
+            lang='fr',
1153 1161
             do_save=True,
1154 1162
             do_notify=False,
1155 1163
         )
@@ -1231,6 +1239,7 @@ class TestUserSetContentAsRead(FunctionalTest):
1231 1239
             name='bob',
1232 1240
             groups=groups,
1233 1241
             timezone='Europe/Paris',
1242
+            lang='fr',
1234 1243
             do_save=True,
1235 1244
             do_notify=False,
1236 1245
         )
@@ -1312,6 +1321,7 @@ class TestUserSetContentAsRead(FunctionalTest):
1312 1321
             name='bob',
1313 1322
             groups=groups,
1314 1323
             timezone='Europe/Paris',
1324
+            lang='fr',
1315 1325
             do_save=True,
1316 1326
             do_notify=False,
1317 1327
         )
@@ -1411,6 +1421,7 @@ class TestUserSetContentAsRead(FunctionalTest):
1411 1421
             name='bob',
1412 1422
             groups=groups,
1413 1423
             timezone='Europe/Paris',
1424
+            lang='fr',
1414 1425
             do_save=True,
1415 1426
             do_notify=False,
1416 1427
         )
@@ -1492,6 +1503,7 @@ class TestUserSetContentAsRead(FunctionalTest):
1492 1503
             name='bob',
1493 1504
             groups=groups,
1494 1505
             timezone='Europe/Paris',
1506
+            lang='fr',
1495 1507
             do_save=True,
1496 1508
             do_notify=False,
1497 1509
         )
@@ -1609,6 +1621,7 @@ class TestUserSetContentAsUnread(FunctionalTest):
1609 1621
             name='bob',
1610 1622
             groups=groups,
1611 1623
             timezone='Europe/Paris',
1624
+            lang='fr',
1612 1625
             do_save=True,
1613 1626
             do_notify=False,
1614 1627
         )
@@ -1718,6 +1731,7 @@ class TestUserSetContentAsUnread(FunctionalTest):
1718 1731
             name='bob',
1719 1732
             groups=groups,
1720 1733
             timezone='Europe/Paris',
1734
+            lang='fr',
1721 1735
             do_save=True,
1722 1736
             do_notify=False,
1723 1737
         )
@@ -1799,6 +1813,7 @@ class TestUserSetContentAsUnread(FunctionalTest):
1799 1813
             name='bob',
1800 1814
             groups=groups,
1801 1815
             timezone='Europe/Paris',
1816
+            lang='fr',
1802 1817
             do_save=True,
1803 1818
             do_notify=False,
1804 1819
         )
@@ -1881,6 +1896,7 @@ class TestUserSetContentAsUnread(FunctionalTest):
1881 1896
             name='bob',
1882 1897
             groups=groups,
1883 1898
             timezone='Europe/Paris',
1899
+            lang='fr',
1884 1900
             do_save=True,
1885 1901
             do_notify=False,
1886 1902
         )
@@ -1976,6 +1992,7 @@ class TestUserSetContentAsUnread(FunctionalTest):
1976 1992
             name='bob',
1977 1993
             groups=groups,
1978 1994
             timezone='Europe/Paris',
1995
+            lang='fr',
1979 1996
             do_save=True,
1980 1997
             do_notify=False,
1981 1998
         )
@@ -2120,6 +2137,7 @@ class TestUserSetWorkspaceAsRead(FunctionalTest):
2120 2137
             name='bob',
2121 2138
             groups=groups,
2122 2139
             timezone='Europe/Paris',
2140
+            lang='fr',
2123 2141
             do_save=True,
2124 2142
             do_notify=False,
2125 2143
         )
@@ -2217,6 +2235,7 @@ class TestUserSetWorkspaceAsRead(FunctionalTest):
2217 2235
             name='bob',
2218 2236
             groups=groups,
2219 2237
             timezone='Europe/Paris',
2238
+            lang='fr',
2220 2239
             do_save=True,
2221 2240
             do_notify=False,
2222 2241
         )
@@ -2314,6 +2333,7 @@ class TestUserSetWorkspaceAsRead(FunctionalTest):
2314 2333
             name='bob',
2315 2334
             groups=groups,
2316 2335
             timezone='Europe/Paris',
2336
+            lang='fr',
2317 2337
             do_save=True,
2318 2338
             do_notify=False,
2319 2339
         )
@@ -2423,7 +2443,6 @@ class TestUserWorkspaceEndpoint(FunctionalTest):
2423 2443
         assert sidebar_entry['hexcolor'] == "#ad4cf9"
2424 2444
         assert sidebar_entry['fa_icon'] == "comments-o"
2425 2445
 
2426
-
2427 2446
     def test_api__get_user_workspaces__err_403__unallowed_user(self):
2428 2447
         """
2429 2448
         Check obtain all workspaces reachables for one user
@@ -2509,6 +2528,7 @@ class TestUserEndpoint(FunctionalTest):
2509 2528
             name='bob',
2510 2529
             groups=groups,
2511 2530
             timezone='Europe/Paris',
2531
+            lang='fr',
2512 2532
             do_save=True,
2513 2533
             do_notify=False,
2514 2534
         )
@@ -2536,6 +2556,7 @@ class TestUserEndpoint(FunctionalTest):
2536 2556
         assert res['public_name'] == 'bob'
2537 2557
         assert res['timezone'] == 'Europe/Paris'
2538 2558
         assert res['is_deleted'] is False
2559
+        assert res['lang'] == 'fr'
2539 2560
 
2540 2561
     def test_api__get_user__ok_200__user_itself(self):
2541 2562
         dbsession = get_tm_session(self.session_factory, transaction.manager)
@@ -2559,6 +2580,7 @@ class TestUserEndpoint(FunctionalTest):
2559 2580
             name='bob',
2560 2581
             groups=groups,
2561 2582
             timezone='Europe/Paris',
2583
+            lang='fr',
2562 2584
             do_save=True,
2563 2585
             do_notify=False,
2564 2586
         )
@@ -2618,6 +2640,7 @@ class TestUserEndpoint(FunctionalTest):
2618 2640
             name='bob2',
2619 2641
             groups=groups,
2620 2642
             timezone='Europe/Paris',
2643
+            lang='fr',
2621 2644
             do_save=True,
2622 2645
             do_notify=False,
2623 2646
         )
@@ -2651,6 +2674,7 @@ class TestUserEndpoint(FunctionalTest):
2651 2674
             'password': 'mysuperpassword',
2652 2675
             'profile': 'users',
2653 2676
             'timezone': 'Europe/Paris',
2677
+            'lang': 'fr',
2654 2678
             'public_name': 'test user',
2655 2679
             'email_notification': False,
2656 2680
         }
@@ -2668,7 +2692,7 @@ class TestUserEndpoint(FunctionalTest):
2668 2692
         assert res['email'] == 'test@test.test'
2669 2693
         assert res['public_name'] == 'test user'
2670 2694
         assert res['timezone'] == 'Europe/Paris'
2671
-
2695
+        assert res['lang'] == 'fr'
2672 2696
         dbsession = get_tm_session(self.session_factory, transaction.manager)
2673 2697
         admin = dbsession.query(models.User) \
2674 2698
             .filter(models.User.email == 'admin@admin.admin') \
@@ -2708,6 +2732,7 @@ class TestUserEndpoint(FunctionalTest):
2708 2732
         assert res['email'] == 'test@test.test'
2709 2733
         assert res['public_name'] == 'test'
2710 2734
         assert res['timezone'] == ''
2735
+        assert res['lang'] is None
2711 2736
 
2712 2737
         dbsession = get_tm_session(self.session_factory, transaction.manager)
2713 2738
         admin = dbsession.query(models.User) \
@@ -2744,6 +2769,7 @@ class TestUserEndpoint(FunctionalTest):
2744 2769
             name='bob',
2745 2770
             groups=groups,
2746 2771
             timezone='Europe/Paris',
2772
+            lang='fr',
2747 2773
             do_save=True,
2748 2774
             do_notify=False,
2749 2775
         )
@@ -2761,6 +2787,7 @@ class TestUserEndpoint(FunctionalTest):
2761 2787
             'password': 'mysuperpassword',
2762 2788
             'profile': 'users',
2763 2789
             'timezone': 'Europe/Paris',
2790
+            'lang': 'fr',
2764 2791
             'public_name': 'test user',
2765 2792
             'email_notification': False,
2766 2793
         }
@@ -2792,6 +2819,7 @@ class TestUserEndpoint(FunctionalTest):
2792 2819
             name='bob',
2793 2820
             groups=groups,
2794 2821
             timezone='Europe/Paris',
2822
+            lang='fr',
2795 2823
             do_save=True,
2796 2824
             do_notify=False,
2797 2825
         )
@@ -2810,6 +2838,7 @@ class TestUserEndpoint(FunctionalTest):
2810 2838
             'profile': 'users',
2811 2839
             'timezone': 'Europe/Paris',
2812 2840
             'public_name': 'test user',
2841
+            'lang': 'fr',
2813 2842
             'email_notification': False,
2814 2843
         }
2815 2844
         res = self.testapp.post_json(
@@ -2840,6 +2869,7 @@ class TestUserWithNotificationEndpoint(FunctionalTest):
2840 2869
             'profile': 'users',
2841 2870
             'timezone': 'Europe/Paris',
2842 2871
             'public_name': 'test user',
2872
+            'lang': 'fr',
2843 2873
             'email_notification': True,
2844 2874
         }
2845 2875
         res = self.testapp.post_json(
@@ -2856,6 +2886,7 @@ class TestUserWithNotificationEndpoint(FunctionalTest):
2856 2886
         assert res['email'] == 'test@test.test'
2857 2887
         assert res['public_name'] == 'test user'
2858 2888
         assert res['timezone'] == 'Europe/Paris'
2889
+        assert res['lang'] == 'fr'
2859 2890
 
2860 2891
         dbsession = get_tm_session(self.session_factory, transaction.manager)
2861 2892
         admin = dbsession.query(models.User) \
@@ -2909,6 +2940,7 @@ class TestUserWithNotificationEndpoint(FunctionalTest):
2909 2940
         assert res['email'] == 'test@test.test'
2910 2941
         assert res['public_name'] == 'test'
2911 2942
         assert res['timezone'] == ''
2943
+        assert res['lang'] == None
2912 2944
 
2913 2945
         dbsession = get_tm_session(self.session_factory, transaction.manager)
2914 2946
         admin = dbsession.query(models.User) \
@@ -2957,6 +2989,7 @@ class TestUserWithNotificationEndpoint(FunctionalTest):
2957 2989
             name='bob',
2958 2990
             groups=groups,
2959 2991
             timezone='Europe/Paris',
2992
+            lang='fr',
2960 2993
             do_save=True,
2961 2994
             do_notify=False,
2962 2995
         )
@@ -3011,6 +3044,7 @@ class TestUsersEndpoint(FunctionalTest):
3011 3044
             name='bob',
3012 3045
             groups=groups,
3013 3046
             timezone='Europe/Paris',
3047
+            lang='fr',
3014 3048
             do_save=True,
3015 3049
             do_notify=False,
3016 3050
         )
@@ -3061,6 +3095,7 @@ class TestUsersEndpoint(FunctionalTest):
3061 3095
             name='bob',
3062 3096
             groups=groups,
3063 3097
             timezone='Europe/Paris',
3098
+            lang='fr',
3064 3099
             do_save=True,
3065 3100
             do_notify=False,
3066 3101
         )
@@ -3110,6 +3145,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3110 3145
             name='bob',
3111 3146
             groups=groups,
3112 3147
             timezone='Europe/Paris',
3148
+            lang='fr',
3113 3149
             do_save=True,
3114 3150
             do_notify=False,
3115 3151
         )
@@ -3119,6 +3155,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3119 3155
             name='bob2',
3120 3156
             groups=groups,
3121 3157
             timezone='Europe/Paris',
3158
+            lang='fr',
3122 3159
             do_save=True,
3123 3160
             do_notify=False,
3124 3161
         )
@@ -3174,6 +3211,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3174 3211
             name='bob',
3175 3212
             groups=groups,
3176 3213
             timezone='Europe/Paris',
3214
+            lang='fr',
3177 3215
             do_save=True,
3178 3216
             do_notify=False,
3179 3217
         )
@@ -3183,6 +3221,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3183 3221
             name='bob2',
3184 3222
             groups=groups,
3185 3223
             timezone='Europe/Paris',
3224
+            lang='fr',
3186 3225
             do_save=True,
3187 3226
             do_notify=False,
3188 3227
         )
@@ -3238,6 +3277,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3238 3277
             name='bob',
3239 3278
             groups=groups,
3240 3279
             timezone='Europe/Paris',
3280
+            lang='fr',
3241 3281
             do_save=True,
3242 3282
             do_notify=False,
3243 3283
         )
@@ -3247,6 +3287,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3247 3287
             name='bob2',
3248 3288
             groups=groups,
3249 3289
             timezone='Europe/Paris',
3290
+            lang='fr',
3250 3291
             do_save=True,
3251 3292
             do_notify=False,
3252 3293
         )
@@ -3292,6 +3333,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3292 3333
             name='bob',
3293 3334
             groups=groups,
3294 3335
             timezone='Europe/Paris',
3336
+            lang='fr',
3295 3337
             do_save=True,
3296 3338
             do_notify=False,
3297 3339
         )
@@ -3301,6 +3343,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3301 3343
             name='bob2',
3302 3344
             groups=groups,
3303 3345
             timezone='Europe/Paris',
3346
+            lang='fr',
3304 3347
             do_save=True,
3305 3348
             do_notify=False,
3306 3349
         )
@@ -3310,6 +3353,7 @@ class TestKnownMembersEndpoint(FunctionalTest):
3310 3353
             name='bob3',
3311 3354
             groups=groups,
3312 3355
             timezone='Europe/Paris',
3356
+            lang='fr',
3313 3357
             do_save=True,
3314 3358
             do_notify=False,
3315 3359
         )
@@ -3395,6 +3439,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3395 3439
             name='bob',
3396 3440
             groups=groups,
3397 3441
             timezone='Europe/Paris',
3442
+            lang='fr',
3398 3443
             do_save=True,
3399 3444
             do_notify=False,
3400 3445
         )
@@ -3457,6 +3502,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3457 3502
             name='bob',
3458 3503
             groups=groups,
3459 3504
             timezone='Europe/Paris',
3505
+            lang='fr',
3460 3506
             do_save=True,
3461 3507
             do_notify=False,
3462 3508
         )
@@ -3519,6 +3565,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3519 3565
             name='bob',
3520 3566
             groups=groups,
3521 3567
             timezone='Europe/Paris',
3568
+            lang='fr',
3522 3569
             do_save=True,
3523 3570
             do_notify=False,
3524 3571
         )
@@ -3581,6 +3628,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3581 3628
             name='bob',
3582 3629
             groups=groups,
3583 3630
             timezone='Europe/Paris',
3631
+            lang='fr',
3584 3632
             do_save=True,
3585 3633
             do_notify=False,
3586 3634
         )
@@ -3643,6 +3691,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3643 3691
             name='bob',
3644 3692
             groups=groups,
3645 3693
             timezone='Europe/Paris',
3694
+            lang='fr',
3646 3695
             do_save=True,
3647 3696
             do_notify=False,
3648 3697
         )
@@ -3712,6 +3761,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3712 3761
             name='bob',
3713 3762
             groups=groups,
3714 3763
             timezone='Europe/Paris',
3764
+            lang='fr',
3715 3765
             do_save=True,
3716 3766
             do_notify=False,
3717 3767
         )
@@ -3721,6 +3771,7 @@ class TestSetEmailEndpoint(FunctionalTest):
3721 3771
             name='bob2',
3722 3772
             groups=groups,
3723 3773
             timezone='Europe/Paris',
3774
+            lang='fr',
3724 3775
             do_save=True,
3725 3776
             do_notify=False,
3726 3777
         )
@@ -3777,6 +3828,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
3777 3828
             name='bob',
3778 3829
             groups=groups,
3779 3830
             timezone='Europe/Paris',
3831
+            lang='fr',
3780 3832
             do_save=True,
3781 3833
             do_notify=False,
3782 3834
         )
@@ -3839,6 +3891,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
3839 3891
             name='bob',
3840 3892
             groups=groups,
3841 3893
             timezone='Europe/Paris',
3894
+            lang='fr',
3842 3895
             do_save=True,
3843 3896
             do_notify=False,
3844 3897
         )
@@ -3901,6 +3954,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
3901 3954
             name='bob',
3902 3955
             groups=groups,
3903 3956
             timezone='Europe/Paris',
3957
+            lang='fr',
3904 3958
             do_save=True,
3905 3959
             do_notify=False,
3906 3960
         )
@@ -3965,6 +4019,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
3965 4019
             name='bob',
3966 4020
             groups=groups,
3967 4021
             timezone='Europe/Paris',
4022
+            lang='fr',
3968 4023
             do_save=True,
3969 4024
             do_notify=False,
3970 4025
         )
@@ -4026,6 +4081,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
4026 4081
             password='pass',
4027 4082
             name='bob',
4028 4083
             groups=groups,
4084
+            lang='fr',
4029 4085
             timezone='Europe/Paris',
4030 4086
             do_save=True,
4031 4087
             do_notify=False,
@@ -4036,6 +4092,7 @@ class TestSetPasswordEndpoint(FunctionalTest):
4036 4092
             name='bob2',
4037 4093
             groups=groups,
4038 4094
             timezone='Europe/Paris',
4095
+            lang='fr',
4039 4096
             do_save=True,
4040 4097
             do_notify=False,
4041 4098
         )
@@ -4092,6 +4149,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4092 4149
             name='bob',
4093 4150
             groups=groups,
4094 4151
             timezone='Europe/Paris',
4152
+            lang='fr',
4095 4153
             do_save=True,
4096 4154
             do_notify=False,
4097 4155
         )
@@ -4115,10 +4173,12 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4115 4173
         assert res['user_id'] == user_id
4116 4174
         assert res['public_name'] == 'bob'
4117 4175
         assert res['timezone'] == 'Europe/Paris'
4176
+        assert res['lang'] == 'fr'
4118 4177
         # Set params
4119 4178
         params = {
4120 4179
             'public_name': 'updated',
4121 4180
             'timezone': 'Europe/London',
4181
+            'lang': 'en',
4122 4182
         }
4123 4183
         self.testapp.put_json(
4124 4184
             '/api/v2/users/{}'.format(user_id),
@@ -4134,6 +4194,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4134 4194
         assert res['user_id'] == user_id
4135 4195
         assert res['public_name'] == 'updated'
4136 4196
         assert res['timezone'] == 'Europe/London'
4197
+        assert res['lang'] == 'en'
4137 4198
 
4138 4199
     def test_api__set_user_info__ok_200__user_itself(self):
4139 4200
         dbsession = get_tm_session(self.session_factory, transaction.manager)
@@ -4157,6 +4218,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4157 4218
             name='bob',
4158 4219
             groups=groups,
4159 4220
             timezone='Europe/Paris',
4221
+            lang='fr',
4160 4222
             do_save=True,
4161 4223
             do_notify=False,
4162 4224
         )
@@ -4180,10 +4242,12 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4180 4242
         assert res['user_id'] == user_id
4181 4243
         assert res['public_name'] == 'bob'
4182 4244
         assert res['timezone'] == 'Europe/Paris'
4245
+        assert res['lang'] == 'fr'
4183 4246
         # Set params
4184 4247
         params = {
4185 4248
             'public_name': 'updated',
4186 4249
             'timezone': 'Europe/London',
4250
+            'lang' : 'en',
4187 4251
         }
4188 4252
         self.testapp.put_json(
4189 4253
             '/api/v2/users/{}'.format(user_id),
@@ -4199,6 +4263,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4199 4263
         assert res['user_id'] == user_id
4200 4264
         assert res['public_name'] == 'updated'
4201 4265
         assert res['timezone'] == 'Europe/London'
4266
+        assert res['lang'] == 'en'
4202 4267
 
4203 4268
     def test_api__set_user_email__err_403__other_normal_user(self):
4204 4269
         dbsession = get_tm_session(self.session_factory, transaction.manager)
@@ -4222,6 +4287,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4222 4287
             name='bob',
4223 4288
             groups=groups,
4224 4289
             timezone='Europe/Paris',
4290
+            lang='fr',
4225 4291
             do_save=True,
4226 4292
             do_notify=False,
4227 4293
         )
@@ -4231,6 +4297,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4231 4297
             name='test',
4232 4298
             groups=groups,
4233 4299
             timezone='Europe/Paris',
4300
+            lang='fr',
4234 4301
             do_save=True,
4235 4302
             do_notify=False,
4236 4303
         )
@@ -4250,6 +4317,7 @@ class TestSetUserInfoEndpoint(FunctionalTest):
4250 4317
         params = {
4251 4318
             'public_name': 'updated',
4252 4319
             'timezone': 'Europe/London',
4320
+            'lang': 'en'
4253 4321
         }
4254 4322
         self.testapp.put_json(
4255 4323
             '/api/v2/users/{}'.format(user_id),
@@ -4287,6 +4355,7 @@ class TestSetUserProfilEndpoint(FunctionalTest):
4287 4355
             name='bob',
4288 4356
             groups=groups,
4289 4357
             timezone='Europe/Paris',
4358
+            lang='fr',
4290 4359
             do_save=True,
4291 4360
             do_notify=False,
4292 4361
         )
@@ -4349,6 +4418,7 @@ class TestSetUserProfilEndpoint(FunctionalTest):
4349 4418
             name='bob',
4350 4419
             groups=groups,
4351 4420
             timezone='Europe/Paris',
4421
+            lang='fr',
4352 4422
             do_save=True,
4353 4423
             do_notify=False,
4354 4424
         )
@@ -4411,6 +4481,7 @@ class TestSetUserProfilEndpoint(FunctionalTest):
4411 4481
             name='bob',
4412 4482
             groups=groups,
4413 4483
             timezone='Europe/Paris',
4484
+            lang='fr',
4414 4485
             do_save=True,
4415 4486
             do_notify=False,
4416 4487
         )
@@ -4420,6 +4491,7 @@ class TestSetUserProfilEndpoint(FunctionalTest):
4420 4491
             name='test',
4421 4492
             groups=groups,
4422 4493
             timezone='Europe/Paris',
4494
+            lang='fr',
4423 4495
             do_save=True,
4424 4496
             do_notify=False,
4425 4497
         )
@@ -4476,6 +4548,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4476 4548
             name='bob',
4477 4549
             groups=groups,
4478 4550
             timezone='Europe/Paris',
4551
+            lang='fr',
4479 4552
             do_save=True,
4480 4553
             do_notify=False,
4481 4554
         )
@@ -4534,6 +4607,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4534 4607
             name='bob',
4535 4608
             groups=groups,
4536 4609
             timezone='Europe/Paris',
4610
+            lang='fr',
4537 4611
             do_save=True,
4538 4612
             do_notify=False,
4539 4613
         )
@@ -4592,6 +4666,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4592 4666
             name='bob',
4593 4667
             groups=groups,
4594 4668
             timezone='Europe/Paris',
4669
+            lang='fr',
4595 4670
             do_save=True,
4596 4671
             do_notify=False,
4597 4672
         )
@@ -4601,6 +4676,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4601 4676
             name='test2',
4602 4677
             groups=groups,
4603 4678
             timezone='Europe/Paris',
4679
+            lang='fr',
4604 4680
             do_save=True,
4605 4681
             do_notify=False,
4606 4682
         )
@@ -4644,6 +4720,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4644 4720
             name='bob',
4645 4721
             groups=groups,
4646 4722
             timezone='Europe/Paris',
4723
+            lang='fr',
4647 4724
             do_save=True,
4648 4725
             do_notify=False,
4649 4726
         )
@@ -4653,6 +4730,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4653 4730
             name='test2',
4654 4731
             groups=groups,
4655 4732
             timezone='Europe/Paris',
4733
+            lang='fr',
4656 4734
             do_save=True,
4657 4735
             do_notify=False,
4658 4736
         )
@@ -4696,6 +4774,7 @@ class TestSetUserEnableDisableEndpoints(FunctionalTest):
4696 4774
             name='bob',
4697 4775
             groups=groups,
4698 4776
             timezone='Europe/Paris',
4777
+            lang='fr',
4699 4778
             do_save=True,
4700 4779
             do_notify=False,
4701 4780
         )

+ 2 - 0
backend/tracim_backend/tests/library/test_user_api.py View File

@@ -55,6 +55,7 @@ class TestUserApi(DefaultTest):
55 55
             password='pass',
56 56
             name='bob',
57 57
             timezone='+2',
58
+            lang='en',
58 59
             do_save=True,
59 60
             do_notify=False,
60 61
         )
@@ -63,6 +64,7 @@ class TestUserApi(DefaultTest):
63 64
         assert u.validate_password('pass')
64 65
         assert u.display_name == 'bob'
65 66
         assert u.timezone == '+2'
67
+        assert u.lang == 'en'
66 68
 
67 69
     def test_unit__user_with_email_exists__ok__nominal_case(self):
68 70
         api = UserApi(

+ 27 - 0
backend/tracim_backend/views/core_api/schemas.py View File

@@ -82,6 +82,7 @@ class UserSchema(UserDigestSchema):
82 82
     )
83 83
     # TODO - G.M - 17-04-2018 - Restrict timezone values
84 84
     timezone = marshmallow.fields.String(
85
+        description="Timezone as tz database format",
85 86
         example="Europe/Paris",
86 87
     )
87 88
     # TODO - G.M - 17-04-2018 - check this, relative url allowed ?
@@ -97,6 +98,14 @@ class UserSchema(UserDigestSchema):
97 98
         validate=OneOf(Profile._NAME),
98 99
         example='managers',
99 100
     )
101
+    lang = marshmallow.fields.String(
102
+        description="User langage in iso639 format",
103
+        example='en',
104
+        required=False,
105
+        validate=Length(min=2, max=3),
106
+        allow_none=True,
107
+        default=None,
108
+    )
100 109
 
101 110
     class Meta:
102 111
         description = 'User account of Tracim'
@@ -136,6 +145,7 @@ class SetPasswordSchema(LoggedInUserPasswordSchema):
136 145
 
137 146
 class UserInfosSchema(marshmallow.Schema):
138 147
     timezone = marshmallow.fields.String(
148
+        description="Timezone as tz database format",
139 149
         example="Europe/Paris",
140 150
         required=True,
141 151
     )
@@ -143,6 +153,14 @@ class UserInfosSchema(marshmallow.Schema):
143 153
         example='Suri Cate',
144 154
         required=True,
145 155
     )
156
+    lang = marshmallow.fields.String(
157
+        description="User langage in iso639 format",
158
+        example='en',
159
+        required=True,
160
+        validate=Length(min=2, max=3),
161
+        allow_none=True,
162
+        default=None,
163
+    )
146 164
 
147 165
     @post_load
148 166
     def create_user_info_object(self, data):
@@ -177,6 +195,7 @@ class UserCreationSchema(marshmallow.Schema):
177 195
         default=Group.TIM_USER_GROUPNAME
178 196
     )
179 197
     timezone = marshmallow.fields.String(
198
+        description="Timezone as tz database format",
180 199
         example="Europe/Paris",
181 200
         required=False,
182 201
         default=''
@@ -186,6 +205,14 @@ class UserCreationSchema(marshmallow.Schema):
186 205
         required=False,
187 206
         default=None,
188 207
     )
208
+    lang = marshmallow.fields.String(
209
+        description="User langage in iso639 format",
210
+        example='en',
211
+        required=False,
212
+        validate=Length(min=2, max=3),
213
+        allow_none=True,
214
+        default=None,
215
+    )
189 216
     email_notification = marshmallow.fields.Bool(
190 217
         example=True,
191 218
         required=False,

+ 2 - 0
backend/tracim_backend/views/core_api/user_controller.py View File

@@ -190,6 +190,7 @@ class UserController(Controller):
190 190
             request.candidate_user,
191 191
             name=hapic_data.body.public_name,
192 192
             timezone=hapic_data.body.timezone,
193
+            lang=hapic_data.body.lang,
193 194
             do_save=True
194 195
         )
195 196
         return uapi.get_user_with_context(user)
@@ -219,6 +220,7 @@ class UserController(Controller):
219 220
             email=hapic_data.body.email,
220 221
             password=hapic_data.body.password,
221 222
             timezone=hapic_data.body.timezone,
223
+            lang=hapic_data.body.lang,
222 224
             name=hapic_data.body.public_name,
223 225
             do_notify=hapic_data.body.email_notification,
224 226
             groups=groups,