def inject_conf_var(): current_language = get_locale() try: current_language_direction = Locale(current_language).text_direction except: current_language_direction = 'ltr' try: available_languages =\ OrderedDict([(lang, Locale(lang).get_language_name(lang).capitalize()) for lang in sort_language_constants()]) except: available_languages = {'en': "English"} # important (!) date needs to be in that exact format (along with minutes/seconds present). # also enter the date in UTC format -> greenwich mean time startDate = '2020/1/7 3:30:00 GMT' launchDate = '2020/1/9 3:00:00 GMT' return dict( CURRENT_LANGUAGE=current_language, CURRENT_LANGUAGE_DIRECTION=current_language_direction, AVAILABLE_LANGUAGES=available_languages, DOMAIN=request.headers['Host'], OGN_LAUNCH_START_DATE=startDate, OGN_LAUNCH_DATE=launchDate, OGN_ALREADY_LAUNCHED=datetime.strptime( launchDate, '%Y/%m/%d %H:%M:%S GMT') < datetime.utcnow(), )
def inject_conf_var(): current_language = get_locale() try: current_language_direction = Locale(current_language).text_direction except: current_language_direction = 'ltr' try: available_languages = dict( (l, Locale(l).get_language_name(l).capitalize()) for l in constants.LANGUAGES) except: available_languages = {'en': "English"} return dict(CURRENT_LANGUAGE=current_language, CURRENT_LANGUAGE_DIRECTION=current_language_direction, AVAILABLE_LANGUAGES=available_languages, DOMAIN=request.headers['Host'])
def edit_user(): styles = "nostyles" in current_user.prefs nsfw = "nsfw" in current_user.prefs exp = "labrat" in current_user.prefs noscroll = "noscroll" in current_user.prefs nochat = "nochat" in current_user.prefs form = EditUserForm( show_nsfw=nsfw, disable_sub_style=styles, experimental=exp, noscroll=noscroll, nochat=nochat, subtheme=current_user.subtheme, language=current_user.language, ) languages = config.app.languages form.language.choices = [("", _("Auto detect"))] for i in languages: form.language.choices.append( (i, Locale(*i.split("_")).display_name.capitalize())) return engine.get_template("user/settings/preferences.html").render({ "edituserform": form, "user": User.get(User.uid == current_user.uid) })
def edit_user(): styles = "nostyles" in current_user.prefs if "nsfw" not in current_user.prefs: nsfw_option = "hide" elif "nsfw_blur" in current_user.prefs: nsfw_option = "blur" else: nsfw_option = "show" exp = "labrat" in current_user.prefs noscroll = "noscroll" in current_user.prefs nochat = "nochat" in current_user.prefs email_notify = "email_notify" in current_user.prefs form = EditUserForm( show_nsfw=nsfw_option, disable_sub_style=styles, experimental=exp, noscroll=noscroll, nochat=nochat, subtheme=current_user.subtheme, language=current_user.language, email_notify=email_notify, ) languages = config.app.languages form.language.choices = [] for i in languages: form.language.choices.append( (i, Locale(*i.split("_")).display_name.capitalize())) return engine.get_template("user/settings/preferences.html").render({ "edituserform": form, "user": User.get(User.uid == current_user.uid) })
def get_supported_locales(): """ Returns a list of Locale objects that the Web Interfaces supports """ locales = BABEL.list_translations() locales.append(Locale("en")) sorted_locales = sorted(locales, key=lambda x: x.language) return sorted_locales
def sort_language_constants(): """ function to generate correct ordering of constants.LANGUAGES list sorted by Unicode characters """ c = Collator() lang_names = [ Locale(lang).get_language_name(lang).capitalize() for lang in constants.LANGUAGES ] available_languages = dict(zip(lang_names, constants.LANGUAGES)) sorted_lang_names = sorted(lang_names, key=c.sort_key) return [available_languages[lang_name] for lang_name in sorted_lang_names]
def add_article(self, page_name, page): components = page_name.split('.') if len(components) == 1: article_id = page_name locale = babel.default_locale else: try: article_id = '.'.join(components[:-1]) locale = Locale(components[-1]) except UnknownLocaleError: article_id = page_name locale = babel.default_locale article = self.articles.get(article_id) if article is None: article = Article(self, article_id) article.default_page = page self.articles[article_id] = article article.localized_pages[locale] = page if locale == babel.default_locale: article.default_page = page
def get_language_names(translation_dir: str, with_native_names: bool = True) -> Iterable[Tuple[str, str]]: """ Get a list of languages supported by the application, each with their name in the current language :param translation_dir: The directory within which the GetText translation folders can be found. :param with_native_names: If set to `True`, the languages' names will not only be given in the current language, but also in their native language. :return: A list of tuples, with the first element being the language code and the second one being the language's name. """ # The language in which the application is currently running. current_locale = get_current_locale() current_language = current_locale.language names = [] languages = get_languages(translation_dir, get_default_language()) for language in languages: # Get the locale for the currently looked at language. locale = Locale(language) # Get the language's name in the current language. name = locale.get_display_name(current_language) # If native names are requested, and the current language is not the one we are currently looking at, # determine the native name. if with_native_names and language != current_language: native_name = locale.get_display_name(language) name = f'{name} ({native_name})' names.append((language, name)) # Sort the list of language names by their name, i.e. the second element in the tuple. # The type ignore is needed until https://github.com/python/mypy/issues/9656 is fixed. names.sort(key=lambda x: x[1]) # type: ignore return names
def test_get_language_names_with_native_names_german( self, mock_listdir: MagicMock, mock_get_current_locale: MagicMock): """ Test getting the list of language names with their native names (with 'de' as locale). Expected result: The list is returned and sorted by their name. """ mock_get_current_locale.return_value = Locale('de') mock_listdir.return_value = [ 'es', 'fr', 'de', ] expected_names = [ ('de', 'Deutsch'), ('en', 'Englisch (English)'), ('fr', 'Französisch (français)'), ('es', 'Spanisch (español)'), ] names = get_language_names(TestConfiguration.TRANSLATION_DIR) mock_listdir.assert_called() self.assertListEqual(expected_names, list(names))
def edit_user(): styles = 'nostyles' in current_user.prefs nsfw = 'nsfw' in current_user.prefs exp = 'labrat' in current_user.prefs noscroll = 'noscroll' in current_user.prefs nochat = 'nochat' in current_user.prefs form = EditUserForm(show_nsfw=nsfw, disable_sub_style=styles, experimental=exp, noscroll=noscroll, nochat=nochat, subtheme=current_user.subtheme, language=current_user.language) languages = config.app.languages form.language.choices = [('', _('Auto detect'))] for i in languages: form.language.choices.append( (i, Locale(*i.split("_")).display_name.capitalize())) return engine.get_template('user/settings/preferences.html').render({ 'edituserform': form, 'user': User.get(User.uid == current_user.uid) })
def create_app(debug=None): app = Flask(__name__) # Configuration files import critiquebrainz.default_config app.config.from_object(critiquebrainz.default_config) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), "..", "config.py"), silent=True) if debug is not None: app.debug = debug # Error handling from critiquebrainz.frontend.error_handlers import init_error_handlers init_error_handlers(app) # Logging from critiquebrainz import loggers loggers.init_loggers(app) if app.debug: # Debug toolbar from flask_debugtoolbar import DebugToolbarExtension DebugToolbarExtension(app) app.config['DEBUG_TB_TEMPLATE_EDITOR_ENABLED'] = True from flask_uuid import FlaskUUID FlaskUUID(app) from critiquebrainz.data import db db.init_app(app) # Memcached if 'MEMCACHED_SERVERS' in app.config: from critiquebrainz import cache cache.init(app.config['MEMCACHED_SERVERS'], app.config['MEMCACHED_NAMESPACE'], debug=1 if app.debug else 0) import critiquebrainz.frontend.babel babel.init_app(app) import critiquebrainz.frontend.login login.login_manager.init_app(app) from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication login.mb_auth = MusicBrainzAuthentication( name='musicbrainz', client_id=app.config['MUSICBRAINZ_CLIENT_ID'], client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'], authorize_url="https://musicbrainz.org/oauth2/authorize", access_token_url="https://musicbrainz.org/oauth2/token", base_url="https://musicbrainz.org/") # APIs from critiquebrainz.frontend.external import mbspotify mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY']) from critiquebrainz.frontend.external import musicbrainz musicbrainz.init(app.config['MUSICBRAINZ_USERAGENT'], critiquebrainz.__version__, hostname=app.config['MUSICBRAINZ_HOSTNAME']) # Template utilities app.jinja_env.add_extension('jinja2.ext.do') from critiquebrainz.utils import reformat_date, reformat_datetime, track_length app.jinja_env.filters['date'] = reformat_date app.jinja_env.filters['datetime'] = reformat_datetime app.jinja_env.filters['track_length'] = track_length app.jinja_env.filters['entity_details'] = musicbrainz.get_entity_by_id app.jinja_env.filters['language_name'] = lambda language_code: Locale( language_code).get_language_name(get_locale()) # Blueprints from critiquebrainz.frontend.views.index import frontend_bp from critiquebrainz.frontend.views.review import review_bp from critiquebrainz.frontend.views.search import search_bp from critiquebrainz.frontend.views.artist import artist_bp from critiquebrainz.frontend.views.release_group import release_group_bp from critiquebrainz.frontend.views.release import release_bp from critiquebrainz.frontend.views.event import event_bp from critiquebrainz.frontend.views.mapping import mapping_bp from critiquebrainz.frontend.views.user import user_bp from critiquebrainz.frontend.views.profile import profile_bp from critiquebrainz.frontend.views.place import place_bp from critiquebrainz.frontend.views.profile_apps import profile_apps_bp from critiquebrainz.frontend.views.login import login_bp from critiquebrainz.frontend.views.oauth import oauth_bp from critiquebrainz.frontend.views.reports import reports_bp from critiquebrainz.frontend.views.log import log_bp app.register_blueprint(frontend_bp) app.register_blueprint(review_bp, url_prefix='/review') app.register_blueprint(search_bp, url_prefix='/search') app.register_blueprint(artist_bp, url_prefix='/artist') app.register_blueprint(release_group_bp, url_prefix='/release-group') app.register_blueprint(release_bp, url_prefix='/release') app.register_blueprint(event_bp, url_prefix='/event') app.register_blueprint(place_bp, url_prefix='/place') app.register_blueprint(mapping_bp, url_prefix='/mapping') app.register_blueprint(user_bp, url_prefix='/user') app.register_blueprint(profile_bp, url_prefix='/profile') app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications') app.register_blueprint(login_bp, url_prefix='/login') app.register_blueprint(oauth_bp, url_prefix='/oauth') app.register_blueprint(reports_bp, url_prefix='/reports') app.register_blueprint(log_bp, url_prefix='/log') return app
def create_app(debug=None, config_path=None): app = CustomFlask( import_name=__name__, use_flask_uuid=True, use_debug_toolbar=True, ) # Configuration files app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'default_config.py' )) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'consul_config.py' ), silent=True) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'custom_config.py' ), silent=True) if config_path: app.config.from_pyfile(config_path) if debug is not None: app.debug = debug # Error handling from critiquebrainz.frontend.error_handlers import init_error_handlers init_error_handlers(app) # Static files from critiquebrainz.frontend import static_manager static_manager.read_manifest() app.init_loggers( file_config=app.config.get("LOG_FILE"), email_config=app.config.get("LOG_EMAIL"), sentry_config=app.config.get("LOG_SENTRY"), ) # Database from critiquebrainz.db import init_db_engine init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI")) add_robots(app) # MusicBrainz Database from critiquebrainz.frontend.external import musicbrainz_db musicbrainz_db.init_db_engine(app.config.get('MB_DATABASE_URI')) # Redis (cache) from brainzutils import cache if "REDIS_HOST" in app.config and \ "REDIS_PORT" in app.config and \ "REDIS_NAMESPACE" in app.config: cache.init( host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"], namespace=app.config["REDIS_NAMESPACE"], ) else: logging.warning("Redis is not defined in config file. Skipping initialization.") from critiquebrainz.frontend import babel babel.init_app(app) from critiquebrainz.frontend import login login.login_manager.init_app(app) from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication login.mb_auth = MusicBrainzAuthentication( name='musicbrainz', client_id=app.config['MUSICBRAINZ_CLIENT_ID'], client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'], authorize_url="https://musicbrainz.org/oauth2/authorize", access_token_url="https://musicbrainz.org/oauth2/token", base_url="https://musicbrainz.org/", ) # APIs from critiquebrainz.frontend.external import mbspotify mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY']) from critiquebrainz.frontend.external import musicbrainz musicbrainz.init( app_name=app.config['MUSICBRAINZ_USERAGENT'] or "CritiqueBrainz Custom", app_version="1.0", hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org", ) # Template utilities app.jinja_env.add_extension('jinja2.ext.do') from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, parameterize from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id app.jinja_env.filters['date'] = reformat_date app.jinja_env.filters['datetime'] = reformat_datetime app.jinja_env.filters['track_length'] = track_length app.jinja_env.filters['parameterize'] = parameterize app.jinja_env.filters['entity_details'] = get_entity_by_id from flask_babel import Locale, get_locale app.jinja_env.filters['language_name'] = lambda language_code: Locale(language_code).get_language_name(get_locale()) app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path)) # Blueprints from critiquebrainz.frontend.views.index import frontend_bp from critiquebrainz.frontend.views.review import review_bp from critiquebrainz.frontend.views.search import search_bp from critiquebrainz.frontend.views.artist import artist_bp from critiquebrainz.frontend.views.release_group import release_group_bp from critiquebrainz.frontend.views.release import release_bp from critiquebrainz.frontend.views.event import event_bp from critiquebrainz.frontend.views.mapping import mapping_bp from critiquebrainz.frontend.views.user import user_bp from critiquebrainz.frontend.views.profile import profile_bp from critiquebrainz.frontend.views.place import place_bp from critiquebrainz.frontend.views.profile_apps import profile_apps_bp from critiquebrainz.frontend.views.login import login_bp from critiquebrainz.frontend.views.oauth import oauth_bp from critiquebrainz.frontend.views.reports import reports_bp from critiquebrainz.frontend.views.moderators import moderators_bp from critiquebrainz.frontend.views.log import log_bp app.register_blueprint(frontend_bp) app.register_blueprint(review_bp, url_prefix='/review') app.register_blueprint(search_bp, url_prefix='/search') app.register_blueprint(artist_bp, url_prefix='/artist') app.register_blueprint(release_group_bp, url_prefix='/release-group') app.register_blueprint(release_bp, url_prefix='/release') app.register_blueprint(event_bp, url_prefix='/event') app.register_blueprint(place_bp, url_prefix='/place') app.register_blueprint(mapping_bp, url_prefix='/mapping') app.register_blueprint(user_bp, url_prefix='/user') app.register_blueprint(profile_bp, url_prefix='/profile') app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications') app.register_blueprint(login_bp, url_prefix='/login') app.register_blueprint(oauth_bp, url_prefix='/oauth') app.register_blueprint(reports_bp, url_prefix='/reports') app.register_blueprint(log_bp, url_prefix='/log') app.register_blueprint(moderators_bp, url_prefix='/moderators') return app
def __repr__(self): locale = get_locale() or Locale('en') lang = LANGUAGES_ISO_MAP.get(locale.language, 'english') return getattr(self.title, lang, '') or ''
def get_available_locale(): return [Locale('en')] + babel.list_translations()
def possible_locales(): """ (TODO) write a GOOD function which gives us all possible Languages """ return [Locale('de'), Locale('en')]
def create_app(debug=None, config_path=None): app = CustomFlask( import_name=__name__, use_flask_uuid=True, ) # Configuration files app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'default_config.py' )) config_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'consul_config.py' ) if deploy_env: print("Checking if consul template generated config file exists: {}".format(config_file)) for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT): if not os.path.exists(config_file): sleep(1) if not os.path.exists(config_file): print("No configuration file generated yet. Retried {} times, exiting.".format(CONSUL_CONFIG_FILE_RETRY_COUNT)) sys.exit(-1) print("Loading consul config file {}".format(config_file)) app.config.from_pyfile(config_file, silent=True) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'custom_config.py' ), silent=True) if config_path: app.config.from_pyfile(config_path) if debug is not None: app.debug = debug if app.debug and app.config['SECRET_KEY']: app.init_debug_toolbar() # Error handling from critiquebrainz.frontend.error_handlers import init_error_handlers init_error_handlers(app) # Static files from critiquebrainz.frontend import static_manager static_manager.read_manifest() app.init_loggers( file_config=app.config.get("LOG_FILE"), email_config=app.config.get("LOG_EMAIL"), sentry_config=app.config.get("LOG_SENTRY"), ) # CritiqueBrainz Database from critiquebrainz import db as critiquebrainz_db critiquebrainz_db.init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI")) add_robots(app) # MusicBrainz Database from brainzutils import musicbrainz_db musicbrainz_db.init_db_engine(app.config.get("MB_DATABASE_URI")) # Redis (cache) from brainzutils import cache if "REDIS_HOST" in app.config and \ "REDIS_PORT" in app.config and \ "REDIS_NAMESPACE" in app.config: cache.init( host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"], namespace=app.config["REDIS_NAMESPACE"], ) else: logging.warning("Redis is not defined in config file. Skipping initialization.") from critiquebrainz.frontend import babel babel.init_app(app) from critiquebrainz.frontend import login login.login_manager.init_app(app) from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication login.mb_auth = MusicBrainzAuthentication( name='musicbrainz', client_id=app.config['MUSICBRAINZ_CLIENT_ID'], client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'], authorize_url="https://musicbrainz.org/oauth2/authorize", access_token_url="https://musicbrainz.org/oauth2/token", base_url="https://musicbrainz.org/", ) # APIs from critiquebrainz.frontend.external import mbspotify mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY']) from critiquebrainz.frontend.external import musicbrainz musicbrainz.init( app_name=app.config['MUSICBRAINZ_USERAGENT'] or "CritiqueBrainz Custom", app_version="1.0", hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org", ) # Template utilities # TODO (code-master5): disabled no-member warnings just as a workaround to deal with failing tests till the # issue [https://github.com/PyCQA/pylint/issues/2563] with pylint is resolved app.jinja_env.add_extension('jinja2.ext.do') from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, track_length_ms, parameterize from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id app.jinja_env.filters['date'] = reformat_date app.jinja_env.filters['datetime'] = reformat_datetime app.jinja_env.filters['track_length'] = track_length app.jinja_env.filters['track_length_ms'] = track_length_ms app.jinja_env.filters['parameterize'] = parameterize app.jinja_env.filters['entity_details'] = get_entity_by_id from flask_babel import Locale, get_locale app.jinja_env.filters['language_name'] = lambda language_code: Locale(language_code).get_language_name(get_locale()) app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path)) # Blueprints from critiquebrainz.frontend.views.index import frontend_bp from critiquebrainz.frontend.views.review import review_bp from critiquebrainz.frontend.views.search import search_bp from critiquebrainz.frontend.views.artist import artist_bp from critiquebrainz.frontend.views.label import label_bp from critiquebrainz.frontend.views.release_group import release_group_bp from critiquebrainz.frontend.views.release import release_bp from critiquebrainz.frontend.views.work import work_bp from critiquebrainz.frontend.views.event import event_bp from critiquebrainz.frontend.views.mapping import mapping_bp from critiquebrainz.frontend.views.user import user_bp from critiquebrainz.frontend.views.profile import profile_bp from critiquebrainz.frontend.views.place import place_bp from critiquebrainz.frontend.views.profile_apps import profile_apps_bp from critiquebrainz.frontend.views.login import login_bp from critiquebrainz.frontend.views.oauth import oauth_bp from critiquebrainz.frontend.views.reports import reports_bp from critiquebrainz.frontend.views.moderators import moderators_bp from critiquebrainz.frontend.views.log import log_bp from critiquebrainz.frontend.views.comment import comment_bp from critiquebrainz.frontend.views.rate import rate_bp from critiquebrainz.frontend.views.statistics import statistics_bp app.register_blueprint(frontend_bp) app.register_blueprint(review_bp, url_prefix='/review') app.register_blueprint(search_bp, url_prefix='/search') app.register_blueprint(artist_bp, url_prefix='/artist') app.register_blueprint(label_bp, url_prefix='/label') app.register_blueprint(release_group_bp, url_prefix='/release-group') app.register_blueprint(release_bp, url_prefix='/release') app.register_blueprint(work_bp, url_prefix='/work') app.register_blueprint(event_bp, url_prefix='/event') app.register_blueprint(place_bp, url_prefix='/place') app.register_blueprint(mapping_bp, url_prefix='/mapping') app.register_blueprint(user_bp, url_prefix='/user') app.register_blueprint(profile_bp, url_prefix='/profile') app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications') app.register_blueprint(login_bp, url_prefix='/login') app.register_blueprint(oauth_bp, url_prefix='/oauth') app.register_blueprint(reports_bp, url_prefix='/reports') app.register_blueprint(log_bp, url_prefix='/log') app.register_blueprint(moderators_bp, url_prefix='/moderators') app.register_blueprint(comment_bp, url_prefix='/comments') app.register_blueprint(rate_bp, url_prefix='/rate') app.register_blueprint(statistics_bp, url_prefix='/statistics') return app
def _user_locale_name(user): l = Locale(user.language) return l.get_display_name(str(l))
class StateAndLength(validators.Length): def __call__(self, form, field): if form.state.data == "draft": return length = len(field.data) if field.data else 0 if length < self.min or self.max != -1 and length > self.max: raise ValidationError(self.message) # Loading supported languages languages = [] for language_code in supported_languages: try: languages.append((language_code, Locale(language_code).language_name)) except UnknownLocaleError: languages.append((language_code, pycountry.languages.get(iso639_1_code=language_code).name)) class ReviewEditForm(FlaskForm): state = StringField(widget=HiddenInput(), default='draft', validators=[validators.DataRequired()]) text = TextAreaField(lazy_gettext("Text"), [ validators.Optional(), StateAndLength(min=MIN_REVIEW_LENGTH, max=MAX_REVIEW_LENGTH, message=lazy_gettext("Text length needs to be between %(min)d and %(max)d characters.", min=MIN_REVIEW_LENGTH, max=MAX_REVIEW_LENGTH))]) license_choice = RadioField( choices=[ ('CC BY-SA 3.0', lazy_gettext('Allow commercial use of this review(<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">CC BY-SA 3.0 license</a>)')), # noqa: E501 ('CC BY-NC-SA 3.0', lazy_gettext('Do not allow commercial use of this review, unless approved by MetaBrainz Foundation (<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/" target="_blank">CC BY-NC-SA 3.0 license</a>)')), # noqa: E501
def to_locale(language): try: return Locale(language) except UnknownLocaleError: return main_locale