Skip to content

Commit

Permalink
simplify get_available_locales()
Browse files Browse the repository at this point in the history
  • Loading branch information
Toby committed Feb 13, 2012
1 parent d4b23c0 commit d0db1be
Showing 1 changed file with 45 additions and 140 deletions.
185 changes: 45 additions & 140 deletions ckan/lib/i18n.py
Original file line number Diff line number Diff line change
@@ -1,154 +1,59 @@
import os

import pylons
from pylons.i18n import _, add_fallback, set_lang, gettext, LanguageError
from pylons.i18n.translation import _get_translator
from pylons.i18n import set_lang
from babel import Locale, localedata
from babel.core import LOCALE_ALIASES
from pylons import config

import ckan.i18n

def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance

i18n_path = os.path.dirname(ckan.i18n.__file__)

@singleton
class Locales(object):
def __init__(self):
from pylons import config

# Get names of the locales
# (must be a better way than scanning for i18n directory?)
known_locales = ['en'] + [locale_name for locale_name in os.listdir(i18n_path) \
if localedata.exists(locale_name)]
self._locale_names, self._default_locale_name = self._work_out_locales(
known_locales, config)
self._locale_objects = map(Locale.parse, self._locale_names)
self._default_locale_object = Locale.parse(self._default_locale_name)

self._aliases = LOCALE_ALIASES
self._aliases['pt'] = 'pt_BR' # Default Portuguese language to
# Brazilian territory, since
# we don't have a Portuguese territory
# translation currently.

def _work_out_locales(self, known_locales, config_dict):
'''Work out the locale_names to offer to the user and the default locale.
All locales in this method are strings, not Locale objects.'''
# pass in a config_dict rather than ckan.config to make this testable

# Get default locale
assert not config_dict.get('lang'), \
'"lang" config option not supported - please use ckan.locale_default instead.'
default_locale = config_dict.get('ckan.locale_default') or \
config_dict.get('ckan.locale') or \
None # in this case, set it later on
if default_locale:
assert default_locale in known_locales

# Filter and reorder locales by config options
def get_locales_in_config_option(config_option):
locales_ = config_dict.get(config_option, '').split()
if locales_:
unknown_locales = set(locales_) - set(known_locales)
assert not unknown_locales, \
'Bad config option %r - locales not found: %s' % \
(config_option, unknown_locales)
return locales_
only_locales_offered = get_locales_in_config_option('ckan.locales_offered')
if only_locales_offered:
locales = only_locales_offered
else:
locales = known_locales

def move_locale_to_start_of_list(locale_):
if locale_ not in locales:
raise ValueError('Cannot find locale "%s" in locales offered.' % locale_)
locales.pop(locales.index(locale_))
locales.insert(0, locale_)

locales_filtered_out = get_locales_in_config_option('ckan.locales_filtered_out')
for locale in locales_filtered_out:
try:
locales.pop(locales.index(locale))
except ValueError, e:
raise ValueError('Could not filter out locale "%s" from offered locale list "%s": %s') % \
(locale, locales, e)

locale_order = get_locales_in_config_option('ckan.locale_order')
if locale_order:
for locale in locale_order[::-1]:
# bring locale_name to the front
try:
move_locale_to_start_of_list(locale)
except ValueError, e:
raise ValueError('Could not process ckan.locale_order options "%s" for offered locale list "%s": %s' % \
(locale_order, locales, e))
elif default_locale:
if default_locale not in locales:
raise ValueError('Default locale "%s" is not amongst locales offered: %s' % \
(default_locale, locales))
# move the default locale to the start of the list
try:
move_locale_to_start_of_list(default_locale)
except ValueError, e:
raise ValueError('Could not move default locale "%s" to the start ofthe list of offered locales "%s": %s' % \
(default_locale, locales, e))

assert locales

if not default_locale:
default_locale = locales[0]
assert default_locale in locales

return locales, default_locale

def get_available_locales(self):
'''Returns a list of the locale objects for which translations are
available.'''
return self._locale_objects

def get_available_locale_names(self):
'''Returns a list of the locale strings for which translations are
available.'''
return self._locale_names

def get_default_locale(self):
'''Returns the default locale/language as specified in the CKAN
config. It is a locale object.'''
return self._default_locale_object

def get_aliases(self):
'''Returns a mapping of language aliases, like the Babel LOCALE_ALIASES
but with hacks for specific CKAN issues.'''
return self._aliases

def negotiate_known_locale(self, preferred_locales):
'''Given a list of preferred locales, this method returns the best
match locale object from the known ones.'''
assert isinstance(preferred_locales, (tuple, list))
preferred_locales = [str(l).replace('-', '_') for l in preferred_locales]
return Locale.parse(Locale.negotiate(preferred_locales,
self.get_available_locale_names(),
aliases=self.get_aliases()
))
LOCALE_ALIASES['pt'] = 'pt_BR' # Default Portuguese language to
# Brazilian territory, since
# we don't have a Portuguese territory
# translation currently.

def _get_locales():

assert not config.get('lang'), \
'"lang" config option not supported - please use ckan.locale_default instead.'
locales_offered = config.get('ckan.locales_offered', '').split()
filtered_out = config.get('ckan.locales_filtered_out', '').split()
locale_order = config.get('ckan.locale_order', '').split()
locale_default = config.get('ckan.locale_default', 'en')

locales = ['en']
i18n_path = os.path.dirname(ckan.i18n.__file__)
locales += [l for l in os.listdir(i18n_path) if localedata.exists(l)]

assert locale_default in locales, \
'default language "%s" not available' % locale_default

locale_list = []
for locale in locales:
if locale in locale_list:
continue
if locales_offered and locale not in locales_offered:
continue
if locale in filtered_out:
continue
if locale == locale_default:
continue
locale_list.append(locale)
ordered_list = [Locale.parse(locale_default)]
for locale in locale_order:
if locale in locale_list:
ordered_list.append(Locale.parse(locale))

return ordered_list

available_locales = None

def get_available_locales():
return Locales().get_available_locales()

def set_session_locale(locale):
if locale not in get_available_locales():
raise ValueError
from pylons import session
session['locale'] = locale
session.save()
if not available_locales:
global available_locales
available_locales = _get_locales()
return available_locales

def handle_request(request, tmpl_context):
lang = request.environ.get('CKAN_LANG', config['ckan.locale_default'])
Expand Down

0 comments on commit d0db1be

Please sign in to comment.