Coverage for portality / internationalise.py: 75%

72 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 00:09 +0100

1from urllib.parse import urlencode 

2 

3from flask import g, request, redirect, url_for, session 

4from flask_babel import Babel 

5 

6DEFAULT_LOCALE = "en" 

7DEFAULT_TIMEZONE = "UTC" 

8LANGUAGES = ['en', 'fr'] 

9INCLUDE_ROUTES = { 

10 'apply', 

11 'account/login' 

12 } 

13 

14def locale_middleware_with_query_params(): 

15 # Get locale from query parameter instead of URL path 

16 lang = request.args.get('lang', DEFAULT_LOCALE) 

17 if lang not in LANGUAGES: 

18 lang = DEFAULT_LOCALE 

19 g.lang = lang # Store in flask.g for easy access 

20 return None # Continue with request 

21 

22def redirect_url(lang: str = DEFAULT_LOCALE): 

23 query_params = request.args.to_dict() 

24 query_params.pop('lang', None) # remove lang from query params which is not required 

25 url_to_redirect = f"/{lang}{request.path}" 

26 if query_params: 

27 url_to_redirect = f"{url_to_redirect}?{urlencode(query_params)}" 

28 return redirect(url_to_redirect) 

29 

30def locale_middleware(): 

31 try: 

32 # Only handle GET requests, let POST pass through 

33 if request.method != 'GET': 

34 return None 

35 

36 # Redirect for included routes 

37 if request.path and any(request.path.strip('/') == f'{route}' for route in INCLUDE_ROUTES): 

38 # update selected language 

39 lang = request.args.get('lang') 

40 if lang: 

41 if lang in LANGUAGES: 

42 session['lang'] = lang 

43 return redirect_url(lang) 

44 

45 if get_url_locale() is None: 

46 return redirect_url(get_session_locale()) 

47 

48 except RuntimeError: 

49 pass 

50 return None 

51 

52def get_url_locale(): 

53 # Get locale from URL 

54 path_parts = request.path.split('/') 

55 if len(path_parts) > 1: 

56 url_locale = path_parts[1] 

57 if url_locale in LANGUAGES: 

58 session['lang'] = url_locale 

59 return url_locale 

60 return None 

61 

62def get_session_locale(): 

63 if 'lang' in session: 

64 lang = session.get('lang') 

65 if lang in LANGUAGES: 

66 return lang 

67 session['lang'] = DEFAULT_LOCALE 

68 return DEFAULT_LOCALE 

69 

70def get_locale(): 

71 lang = get_url_locale() 

72 if lang is None: 

73 lang = DEFAULT_LOCALE 

74 

75 return lang 

76 

77def get_timezone(): 

78 user = getattr(g, 'user', None) 

79 if user is not None: 

80 return user.timezone 

81 

82 return DEFAULT_TIMEZONE 

83 

84 

85def url_for_other_page(endpoint, **kwargs): 

86 if 'lang' not in kwargs: 

87 kwargs['lang'] = g.get('lang', DEFAULT_LOCALE) 

88 return url_for(endpoint, **kwargs) 

89 

90def internationalise(app): 

91 # Initialize internationalization using Flask-Babel 

92 app.config['BABEL_DEFAULT_LOCALE'] = DEFAULT_LOCALE # Default 

93 app.config['BABEL_DEFAULT_TIMEZONE'] = DEFAULT_TIMEZONE 

94 app.config['LANGUAGES'] = LANGUAGES 

95 app.config['BABEL_TRANSLATION_DIRECTORIES'] = "ui/translations" 

96 

97 app.babel = Babel(app, locale_selector=get_locale, timezone_selector=get_timezone) 

98 

99 # Add locale middleware 

100 app.before_request(locale_middleware) 

101 

102 # Add to template context 

103 app.jinja_env.globals['url_for_other_page'] = url_for_other_page 

104