From 0745f5bf18f30d0a5c8b416bb056a43e7e2de4dc Mon Sep 17 00:00:00 2001 From: KeyserSosa Date: Wed, 13 May 2009 11:13:00 -0700 Subject: [PATCH 1/5] make 1/2 of the default reddits English reddits if the user hasn't set their language preferences and is coming from a non-en-default browser. Also clean up and remvove old subredditbox code. --- r2/example.ini | 3 +- r2/r2/controllers/listingcontroller.py | 3 +- r2/r2/controllers/reddit_base.py | 9 ++-- r2/r2/controllers/validator/validator.py | 2 +- r2/r2/lib/app_globals.py | 7 +-- r2/r2/lib/organic.py | 2 +- r2/r2/lib/pages/pages.py | 58 ++++------------------ r2/r2/lib/strings.py | 7 +-- r2/r2/lib/translation.py | 14 +++--- r2/r2/lib/utils/utils.py | 7 +++ r2/r2/models/account.py | 4 +- r2/r2/models/subreddit.py | 60 +++++++++++++++-------- r2/r2/public/static/css/reddit.css | 39 --------------- r2/r2/templates/createsubreddit.html | 2 +- r2/r2/templates/prefoptions.html | 2 +- r2/r2/templates/redditfooter.html | 2 +- r2/r2/templates/subredditbox.html | 61 ------------------------ r2/r2/templates/utils.html | 2 +- 18 files changed, 90 insertions(+), 194 deletions(-) delete mode 100644 r2/r2/templates/subredditbox.html diff --git a/r2/example.ini b/r2/example.ini index 73c011969..2f94be872 100644 --- a/r2/example.ini +++ b/r2/example.ini @@ -71,6 +71,7 @@ db_table_report_account_subreddit = relation, account, subreddit, main ### timezone = UTC +lang = en monitored_servers = localhost #query cache settings @@ -130,7 +131,7 @@ RATELIMIT = 10 num_comments = 200 max_comments = 500 -num_side_reddits = 20 +num_default_reddits = 10 smtp_server = localhost new_link_share_delay = 5 minutes diff --git a/r2/r2/controllers/listingcontroller.py b/r2/r2/controllers/listingcontroller.py index 91c3467f4..eb048cb2c 100644 --- a/r2/r2/controllers/listingcontroller.py +++ b/r2/r2/controllers/listingcontroller.py @@ -221,7 +221,8 @@ class HotController(FixListing, ListingController): if c.site == Default: user = c.user if c.user_is_loggedin else None - sr_ids = Subreddit.user_subreddits(user) + sr_ids = Subreddit.user_subreddits(user, + limit = g.num_default_reddits) return normalized_hot(sr_ids) #if not using the query_cache we still want cached front pages elif (not g.use_query_cache diff --git a/r2/r2/controllers/reddit_base.py b/r2/r2/controllers/reddit_base.py index a5a83aaa8..13e928171 100644 --- a/r2/r2/controllers/reddit_base.py +++ b/r2/r2/controllers/reddit_base.py @@ -80,9 +80,12 @@ class UnloggedUser(FakeAccount): if browser_langs: lang = browser_langs[0] content_langs = list(browser_langs) + # try to coerce the default language + if g.lang not in content_langs: + content_langs.append(g.lang) content_langs.sort() else: - lang = 'en' + lang = g.lang content_langs = 'all' self._defaults = self._defaults.copy() self._defaults['pref_lang'] = lang @@ -297,7 +300,7 @@ def set_iface_lang(): # (used for formatting of large numbers to break them up with ","). # unfortunately, not directly compatible with gettext locale.setlocale(locale.LC_ALL, g.locale) - lang = ['en'] + lang = [g.lang] # GET param wins if c.host_lang: lang = [c.host_lang] @@ -316,7 +319,7 @@ def set_iface_lang(): break except h.LanguageError: #we don't have a translation for that language - h.set_lang('en', graceful_fail = True) + h.set_lang(g.lang, graceful_fail = True) #TODO: add exceptions here for rtl languages if c.lang in ('ar', 'he', 'fa'): diff --git a/r2/r2/controllers/validator/validator.py b/r2/r2/controllers/validator/validator.py index 7c718ecaf..37857cf22 100644 --- a/r2/r2/controllers/validator/validator.py +++ b/r2/r2/controllers/validator/validator.py @@ -181,7 +181,7 @@ class VLang(Validator): if lang in g.all_languages: return lang #else - return 'en' + return g.lang class VRequired(Validator): def __init__(self, param, error, *a, **kw): diff --git a/r2/r2/lib/app_globals.py b/r2/r2/lib/app_globals.py index 86b850d80..8e0eb047d 100644 --- a/r2/r2/lib/app_globals.py +++ b/r2/r2/lib/app_globals.py @@ -25,7 +25,7 @@ import pytz, os, logging, sys, socket from datetime import timedelta from r2.lib.cache import LocalCache, Memcache, CacheChain from r2.lib.db.stats import QueryStats -from r2.lib.translation import _get_languages +from r2.lib.translation import get_active_langs from r2.lib.lock import make_lock_factory from r2.lib.manager import db_manager @@ -44,7 +44,7 @@ class Globals(object): 'RATELIMIT', 'num_comments', 'max_comments', - 'num_side_reddits', + 'num_default_reddits', 'num_query_queue_workers', 'max_sr_images', ] @@ -131,7 +131,8 @@ class Globals(object): self.REDDIT_MAIN = bool(os.environ.get('REDDIT_MAIN')) # turn on for language support - self.languages, self.lang_name = _get_languages() + self.languages, self.lang_name = \ + get_active_langs(default_lang= self.lang) all_languages = self.lang_name.keys() all_languages.sort() diff --git a/r2/r2/lib/organic.py b/r2/r2/lib/organic.py index b60c5fd4e..61269f237 100644 --- a/r2/r2/lib/organic.py +++ b/r2/r2/lib/organic.py @@ -96,7 +96,7 @@ def insert_promoted(link_names, sr_ids, logged_in): @memoize('cached_organic_links', time = organic_lifetime) def cached_organic_links(user_id, langs): if user_id is None: - sr_ids = Subreddit.default_srs(langs, ids = True) + sr_ids = Subreddit.user_subreddits(None) else: user = Account._byID(user_id, data=True) sr_ids = Subreddit.user_subreddits(user) diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 456380d5b..58965cbc5 100644 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -748,8 +748,7 @@ class SubredditTopBar(Wrapped): title = _('my reddits'), type = 'srdrop') - - pop_reddits = Subreddit.default_srs(c.content_langs, limit = 30) + pop_reddits = Subreddit.user_subreddits(None, ids = False) buttons = [SubredditButton(sr) for sr in c.recent_reddits] for sr in pop_reddits: if sr not in c.recent_reddits: @@ -758,57 +757,18 @@ class SubredditTopBar(Wrapped): self.sr_bar = NavMenu(buttons, type='flatlist', separator = '-', _id = 'sr-bar') -class SubredditBox(Wrapped): - """A content pane that has the lists of subreddits that go in the - right pane by default""" - def __init__(self): - Wrapped.__init__(self) - - self.title = _('Other reddit communities') - self.subtitle = 'Visit your subscribed reddits (in bold) or explore new ones' - self.create_link = ('/reddits/', menu.more) - self.more_link = ('/reddits/create', _('create')) - - my_reddits = [] - sr_ids = Subreddit.user_subreddits(c.user if c.user_is_loggedin else None) - if sr_ids: - my_reddits = Subreddit._byID(sr_ids, True, - return_dict = False) - my_reddits.sort(key = lambda sr: sr._downs, reverse = True) - - display_reddits = my_reddits[:g.num_side_reddits] - - #remove the current reddit - display_reddits = filter(lambda x: x != c.site, display_reddits) - - pop_reddits = Subreddit.default_srs(c.content_langs, limit = g.num_side_reddits) - #add english reddits to the list - if c.content_langs != 'all' and 'en' not in c.content_langs: - en_reddits = Subreddit.default_srs(['en']) - pop_reddits += [sr for sr in en_reddits if sr not in pop_reddits] - - for sr in pop_reddits: - if len(display_reddits) >= g.num_side_reddits: - break - - if sr != c.site and sr not in display_reddits: - display_reddits.append(sr) - - col1, col2 = [], [] - cur_col, other = col1, col2 - for sr in display_reddits: - cur_col.append((sr, sr in my_reddits)) - cur_col, other = other, cur_col - - self.cols = ((col1, col2)) - self.mine = my_reddits - class SubscriptionBox(Wrapped): """The list of reddits a user is currently subscribed to to go in the right pane.""" def __init__(self): - sr_ids = Subreddit.user_subreddits(c.user if c.user_is_loggedin else None) - srs = Subreddit._byID(sr_ids, True, return_dict = False) + user = c.user if c.user_is_loggedin else None + # user_subreddits does know to limit to just + # g.num_default_reddits if the user is not subscribed. + if not user or not user.has_subscribed: + limit = g.num_default_reddits + else: + limit = Subreddit.sr_limit + srs = Subreddit.user_subreddits(user, ids = False, limit = limit) srs.sort(key = lambda sr: sr.name.lower()) b = IDBuilder([sr._fullname for sr in srs]) self.reddits = LinkListing(b).listing().things diff --git a/r2/r2/lib/strings.py b/r2/r2/lib/strings.py index dd80d7195..51c64a97e 100644 --- a/r2/r2/lib/strings.py +++ b/r2/r2/lib/strings.py @@ -28,6 +28,7 @@ hooks to the UI are the same. """ import helpers as h +from pylons import g from pylons.i18n import _, ungettext import random @@ -220,14 +221,14 @@ class Score(object): def fallback_trans(x): """For translating placeholder strings the user should never see in raw form, such as 'funny 500 message'. If the string does not - translate in the current language, falls back on the 'en' + translate in the current language, falls back on the g.lang translation that we've hopefully already provided""" t = _(x) if t == x: l = h.get_lang() - h.set_lang('en', graceful_fail = True) + h.set_lang(g.lang, graceful_fail = True) t = _(x) - if l and l[0] != 'en': + if l and l[0] != g.lang: h.set_lang(l[0]) return t diff --git a/r2/r2/lib/translation.py b/r2/r2/lib/translation.py index 0215f528a..bcc6b516e 100644 --- a/r2/r2/lib/translation.py +++ b/r2/r2/lib/translation.py @@ -477,7 +477,8 @@ class Translator(LoggedSlots): @classmethod - def get_slots(cls, locale = 'en'): + def get_slots(cls, locale = None): + locale = locale or pylons.g.lang f = cls.outfile(locale, extension='data') return LoggedSlots._get_slots(f) @@ -571,7 +572,7 @@ def _rebuild_trans(path = _i18n_path): t.save(compile = True) -def _get_languages(path = _i18n_path): +def get_active_langs(path = _i18n_path, default_lang = 'en'): trans = [] trans_name = {} for lang in os.listdir(path): @@ -580,14 +581,15 @@ def _get_languages(path = _i18n_path): name = Translator.get_name(lang) trans_name[lang] = name if Translator.is_enabled(lang) and Translator.in_use(lang): - # en is treated specially - if lang != 'en': + if lang != default_lang: trans.append(lang) if Translator.get_complete_frac(lang) < .5: name += ' (*)' trans.sort() - trans.insert(0, 'en') - trans_name['en'] = "English" + # insert the default language at the top of the list + trans.insert(0, default_lang) + if default_lang not in trans_name: + trans_name[default_lang] = default_lang return trans, trans_name diff --git a/r2/r2/lib/utils/utils.py b/r2/r2/lib/utils/utils.py index 96d9d81de..a8a9e09e1 100644 --- a/r2/r2/lib/utils/utils.py +++ b/r2/r2/lib/utils/utils.py @@ -1030,3 +1030,10 @@ def common_subdomain(domain1, domain2): if domain2.endswith(d): return d return "" + +def interleave_lists(*args): + max_len = max(len(x) for x in args) + for i in xrange(max_len): + for a in args: + if i < len(a): + yield a[i] diff --git a/r2/r2/models/account.py b/r2/r2/models/account.py index 36359753a..ad33efb11 100644 --- a/r2/r2/models/account.py +++ b/r2/r2/models/account.py @@ -46,8 +46,8 @@ class Account(Thing): pref_min_link_score = -4, pref_min_comment_score = -4, pref_num_comments = g.num_comments, - pref_lang = 'en', - pref_content_langs = ('en',), + pref_lang = g.lang, + pref_content_langs = (g.lang,), pref_over_18 = False, pref_compress = False, pref_organic = True, diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index 9ae0796ef..8254893d6 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -30,7 +30,7 @@ from printable import Printable from r2.lib.db.userrel import UserRel from r2.lib.db.operators import lower, or_, and_, desc from r2.lib.memoize import memoize -from r2.lib.utils import tup +from r2.lib.utils import tup, interleave_lists from r2.lib.strings import strings, Score from r2.lib.filters import _force_unicode @@ -58,7 +58,7 @@ class Subreddit(Thing, Printable): sr_limit = 50 @classmethod - def _new(self, name, title, author_id, ip, lang = 'en', type = 'public', + def _new(self, name, title, author_id, ip, lang = g.lang, type = 'public', over_18 = False, **kw): with g.make_lock('create_sr_' + name.lower()): try: @@ -243,7 +243,8 @@ class Subreddit(Thing, Printable): def add_props(cls, user, wrapped): names = ('subscriber', 'moderator', 'contributor') rels = (SRMember._fast_query(wrapped, [user], names) if user else {}) - defaults = Subreddit.default_srs(c.content_langs, ids = True) + defaults = Subreddit.user_subreddits(None, + limit = g.num_default_reddits) for item in wrapped: if not user or not user.has_subscribed: item.subscriber = item._id in defaults @@ -276,10 +277,11 @@ class Subreddit(Thing, Printable): #return 1 @classmethod - def default_srs(cls, lang, ids = False, limit = 10): + def default_srs(cls, lang, limit): """Returns the default list of subreddits for a given language, sorted by popularity""" - pop_reddits = Subreddit._query(Subreddit.c.type == ('public', 'restricted'), + pop_reddits = Subreddit._query(Subreddit.c.type == ('public', + 'restricted'), sort=desc('_downs'), limit = limit, data = True, @@ -292,36 +294,54 @@ class Subreddit(Thing, Printable): if not c.over18: pop_reddits._filter(Subreddit.c.over_18 == False) - pop_reddits = list(pop_reddits) - - if not pop_reddits and lang != 'en': - pop_reddits = cls.default_srs('en') - - return [s._id for s in pop_reddits] if ids else list(pop_reddits) + return list(pop_reddits) @classmethod - def user_subreddits(cls, user, limit = sr_limit): - """subreddits that appear in a user's listings. returns the default - srs if there are no subscriptions.""" + def user_subreddits(cls, user, ids = True, limit = sr_limit): + """ + subreddits that appear in a user's listings. If the user has + subscribed, returns the stored set of subscriptions. + + Otherwise, returns a set of 'limit' subreddits, making sure to + include a fair bit of content from the default language. + """ if user and user.has_subscribed: sr_ids = Subreddit.reverse_subscriber_ids(user) if limit and len(sr_ids) > limit: - return random.sample(sr_ids, limit) - else: - return sr_ids + sr_ids = random.sample(sr_ids, limit) + return sr_ids if ids else Subreddit._byID(sr_ids, True, False) else: - return cls.default_srs(c.content_langs, ids = True) + langs = list(c.content_langs) + # g.lang will be in the the current set of content langs + # unless the user has explicity removed it. Since most + # content is in g.lang, set the subreddit ratio to 50/50. + if limit and langs != 'all' and g.lang in langs and len(langs) != 1: + # lookup default lang subreddits + default_srs = cls.default_srs([g.lang], limit) + # remove g.lang from conten_lang list and use it to + # grab content_lang subreddits + langs.remove(g.lang) + lang_srs = cls.default_srs(langs, limit) + # interleave the two lists, putting the lang ones first + srs = list(interleave_lists(lang_srs, default_srs)) + if limit: + srs = srs[:limit] + else: + # the user knows better and has set their langs accordingly + srs = cls.default_srs(c.content_langs, limit) + return [s._id for s in srs] if ids else srs def is_subscriber_defaults(self, user): if user.has_subscribed: return self.is_subscriber(user) else: - return self in self.default_srs(c.content_langs) + return self in self.user_subreddits(None, ids = False) @classmethod def subscribe_defaults(cls, user): if not user.has_subscribed: - for sr in Subreddit.default_srs(c.content_langs): + for sr in cls.user_subreddits(None, False, + limit = g.num_default_reddits): #this will call reverse_subscriber_ids after every #addition. if it becomes a problem we should make an #add_multiple_subscriber fn diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css index f3aae2084..ed527beec 100644 --- a/r2/r2/public/static/css/reddit.css +++ b/r2/r2/public/static/css/reddit.css @@ -281,45 +281,6 @@ ul.flat-vert {text-align: left;} margin: 7px 0; } -.subredditbox { - border: 1px solid gray; -} - -.subredditbox h4 { - font-size: 170%; - color: #333; - padding: 5px 0 0 5px; -} -.subredditbox h5 { - font-weight: normal; - color: dimgray; - font-size: 110%; - padding-left: 5px; -} - -.subredditbox input[type=submit] { - border: none; - background-color: white; - text-decoration: underline; - cursor: pointer; - margin-left: 10px; - color: #369; -} - -.subredditbox input[type=checkbox] {margin-right: 5px;} - -.subredditbox ul { - padding: 5px; - width: 139px; - list-style-type: none; - float: left; -} - -.subredditbox li {padding: 4px; text-transform: uppercase;} -.subredditbox li a {color: #369;} -.subredditbox li.selected a{font-weight: bold;} -.subredditbox .spacer { margin: 5px 0 } - .morelink { background-color:#FFFFFF; color:#369; diff --git a/r2/r2/templates/createsubreddit.html b/r2/r2/templates/createsubreddit.html index 78b0c5e55..1e2440b91 100644 --- a/r2/r2/templates/createsubreddit.html +++ b/r2/r2/templates/createsubreddit.html @@ -140,7 +140,7 @@ function update_title(elem) { <% default_lang = thing.site and thing.site.lang or c.lang or '' default_lang = default_lang.split('-')[0] - default_lang = 'en' if len(default_lang) != 2 else default_lang + default_lang = g.lang if len(default_lang) != 2 else default_lang %> ${language_tool(all_langs = True, default_lang = default_lang)} diff --git a/r2/r2/templates/prefoptions.html b/r2/r2/templates/prefoptions.html index 1ad7713a9..e22eba3a3 100644 --- a/r2/r2/templates/prefoptions.html +++ b/r2/r2/templates/prefoptions.html @@ -69,7 +69,7 @@ else: action = "/post/unlogged_options" if not c.frameless_cname: - action = add_sr(action, nocname=True) + action = add_sr(action, sr_path = False, nocname=True) %>
diff --git a/r2/r2/templates/redditfooter.html b/r2/r2/templates/redditfooter.html index 99fb98687..9bb960801 100644 --- a/r2/r2/templates/redditfooter.html +++ b/r2/r2/templates/redditfooter.html @@ -76,7 +76,7 @@