def send_to_all(self, recipients, subject, body, format=None): """ Sends an email to all recipients and does the translation. """ if not format: format = {} for recipient in recipients: if not recipient: logging.warning("Ignoring empty recipient.") continue # We try to get more information about the user from the database # like the locale. user = self.pakfire.users.get_by_email(recipient) if user: # Get locale that the user prefers. locale = tornado.locale.get(user.locale) else: # Get the default locale. locale = tornado.locale.get() # Translate the message. _subject = locale.translate(subject) % format _body = locale.translate(body) % format # If we know the real name of the user we add the realname to # the recipient field. if user: recipient = "%s <%s>" % (user.realname, user.email) # Add the message to the queue that it is sent. self.add(recipient, _subject, _body)
def format_amount_of_time(seconds, precision=2, locale=None): """Return the number of seconds formatted 'X days, Y hours, ...' The time units that will be used are days, hours, minutes, seconds. Only the first "precision" units will be output. If they're not enough, a "more than ..." will be prefixed (non-positive precision means infinite). seconds (int): the length of the amount of time in seconds. precision (int): see above locale (tornado.locale.Locale): the locale to be used. return (string): seconds formatted as above. """ seconds = abs(int(seconds)) if locale is None: locale = tornado.locale.get() if seconds == 0: return locale.translate("0 seconds") units = [("day", 60 * 60 * 24), ("hour", 60 * 60), ("minute", 60), ("second", 1)] ret = list() counter = 0 for name, length in units: tmp = seconds // length seconds %= length if tmp == 0: continue elif tmp == 1: ret.append(locale.translate("1 %s" % name)) else: ret.append(locale.translate("%%d %ss" % name) % tmp) counter += 1 if counter == precision: break ret = locale.list(ret) if seconds > 0: ret = locale.translate("more than %s") % ret return ret
def TLU(self, *args, **kwargs): """Return a translated string in the user's locale inferred by Tornado, falling back to u2606 locale if it can't.""" if self.application.hb_config["ignore_browser_locale"]: return self.TL(*args, **kwargs) locale = self.get_browser_locale(self.application.hb_config["language"]) return locale.translate(*args, **kwargs)
def test_csv(self): tornado.locale.load_translations( os.path.join(os.path.dirname(__file__), "csv_translations") ) locale = tornado.locale.get("fr_FR") self.assertTrue(isinstance(locale, tornado.locale.CSVLocale)) self.assertEqual(locale.translate("school"), u"\u00e9cole")
def test_gettext(self): tornado.locale.load_gettext_translations( os.path.join(os.path.dirname(__file__), 'gettext_translations'), "tornado_test") locale = tornado.locale.get("fr_FR") self.assertTrue(isinstance(locale, tornado.locale.GettextLocale)) self.assertEqual(locale.translate("school"), u"\u00e9cole")
def format_datetime_smart(dt, timezone, locale=None): """Return dt formatted as 'date & time' or, if date is today, just 'time' dt (datetime): a datetime object timezone (subclass of tzinfo): the timezone the output should be in return (str): the [date and] time of dt, formatted using the given locale """ if locale is None: locale = tornado.locale.get() # convert dt and 'now' from UTC to local time dt = dt.replace(tzinfo=utc).astimezone(timezone) now = make_datetime().replace(tzinfo=utc).astimezone(timezone) if dt.date() == now.date(): return dt.strftime(locale.translate("%H:%M:%S")) else: return dt.strftime(locale.translate("%Y-%m-%d %H:%M:%S"))
def daily(hours): now = time.time() offset = 0 post_ids_to_email = set() while True: index_posts = conn.query( "SELECT * FROM index_posts ORDER BY rank DESC LIMIT %s, 100", offset) if len(index_posts) == 0: break post_ids = [post["entity_id"] for post in index_posts] for post_id, post in nomagic._get_entities_by_ids(post_ids): period = (now - time.mktime( datetime.datetime.strptime( post["datetime"], "%Y-%m-%dT%H:%M:%S.%f").timetuple())) / 3600 if period <= hours: post_ids_to_email.add(post_id) offset += 100 posts_to_email = nomagic._get_entities_by_ids(post_ids_to_email) loader = tornado.template.Loader( os.path.dirname(os.path.abspath(__file__)) + "/../template/") locale = tornado.locale.get() msg = amazon_ses.EmailMessage() msg.subject = locale.translate('Pythonic Info Daily').encode("utf-8") msg.bodyHtml = loader.load("email_daily.html").generate( posts=posts_to_email, _=locale.translate) users = [] users_not_to_send = [] users_exists = conn.query("SELECT * FROM index_login") for user_id, user in nomagic._get_entities_by_ids( [user_exists["entity_id"] for user_exists in users_exists]): if user.get("receive_daily_email", True): users.append(user) else: users_not_to_send.append(user) users_invited = conn.query("SELECT * FROM invite") sender = amazon_ses.AmazonSES(settings["AmazonAccessKeyID"], settings["AmazonSecretAccessKey"]) emails = set([user["login"] for user in users_exists] + [user["email"] for user in users_invited]) - set( [user["email"] for user in users_not_to_send]) for email in emails: if "@" in email: print email sender.sendEmail(settings["email_sender"], email, msg)
def test_gettext(self): tornado.locale.load_gettext_translations( os.path.join(os.path.dirname(__file__), 'gettext_translations'), "tornado_test") locale = tornado.locale.get("fr_FR") self.assertTrue(isinstance(locale, tornado.locale.GettextLocale)) self.assertEqual(locale.translate("school"), u("\u00e9cole")) self.assertEqual(locale.pgettext("law", "right"), u("le droit")) self.assertEqual(locale.pgettext("good", "right"), u("le bien")) self.assertEqual(locale.pgettext("organization", "club", "clubs", 1), u("le club")) self.assertEqual(locale.pgettext("organization", "club", "clubs", 2), u("les clubs")) self.assertEqual(locale.pgettext("stick", "club", "clubs", 1), u("le b\xe2ton")) self.assertEqual(locale.pgettext("stick", "club", "clubs", 2), u("les b\xe2tons"))
def test_gettext(self): tornado.locale.load_gettext_translations( os.path.join(os.path.dirname(__file__), 'gettext_translations'), "tornado_test") locale = tornado.locale.get("fr_FR") self.assertTrue(isinstance(locale, tornado.locale.GettextLocale)) self.assertEqual(locale.translate("school"), u"\u00e9cole") self.assertEqual(locale.pgettext("law", "right"), u"le droit") self.assertEqual(locale.pgettext("good", "right"), u"le bien") self.assertEqual(locale.pgettext("organization", "club", "clubs", 1), u"le club") self.assertEqual(locale.pgettext("organization", "club", "clubs", 2), u"les clubs") self.assertEqual(locale.pgettext("stick", "club", "clubs", 1), u"le b\xe2ton") self.assertEqual(locale.pgettext("stick", "club", "clubs", 2), u"les b\xe2tons")
def format_datetime(dt, timezone, locale=None): """Return the date and time of dt formatted according to the given locale dt (datetime): a datetime object timezone (subclass of tzinfo): the timezone the output should be in return (str): the date and time of dt, formatted using the given locale """ if locale is None: locale = tornado.locale.get() # convert dt from UTC to local time dt = dt.replace(tzinfo=utc).astimezone(timezone) return dt.strftime(locale.translate("%Y-%m-%d %H:%M:%S"))
def test_csv_bom(self): with open(os.path.join(os.path.dirname(__file__), "csv_translations", "fr_FR.csv"), "rb") as f: char_data = to_unicode(f.read()) # Re-encode our input data (which is utf-8 without BOM) in # encodings that use the BOM and ensure that we can still load # it. Note that utf-16-le and utf-16-be do not write a BOM, # so we only test whichver variant is native to our platform. for encoding in ["utf-8-sig", "utf-16"]: tmpdir = tempfile.mkdtemp() try: with open(os.path.join(tmpdir, "fr_FR.csv"), "wb") as f: f.write(char_data.encode(encoding)) tornado.locale.load_translations(tmpdir) locale = tornado.locale.get("fr_FR") self.assertIsInstance(locale, tornado.locale.CSVLocale) self.assertEqual(locale.translate("school"), u("\u00e9cole")) finally: shutil.rmtree(tmpdir)
def daily(hours): now = time.time() offset = 0 post_ids_to_email = set() while True: index_posts = conn.query("SELECT * FROM index_posts ORDER BY rank DESC LIMIT %s, 100", offset) if len(index_posts) == 0: break post_ids = [post["entity_id"] for post in index_posts] for post_id, post in nomagic._get_entities_by_ids(post_ids): period = (now - time.mktime(datetime.datetime.strptime(post["datetime"], "%Y-%m-%dT%H:%M:%S.%f").timetuple())) / 3600 if period <= hours: post_ids_to_email.add(post_id) offset += 100 posts_to_email = nomagic._get_entities_by_ids(post_ids_to_email) loader = tornado.template.Loader(os.path.dirname(os.path.abspath(__file__)) + "/../template/") locale = tornado.locale.get() msg = amazon_ses.EmailMessage() msg.subject = locale.translate('Pythonic Info Daily').encode("utf-8") msg.bodyHtml = loader.load("email_daily.html").generate(posts=posts_to_email, _=locale.translate) users = [] users_not_to_send = [] users_exists = conn.query("SELECT * FROM index_login") for user_id, user in nomagic._get_entities_by_ids([user_exists["entity_id"] for user_exists in users_exists]): if user.get("receive_daily_email", True): users.append(user) else: users_not_to_send.append(user) users_invited = conn.query("SELECT * FROM invite") sender = amazon_ses.AmazonSES(settings["AmazonAccessKeyID"], settings["AmazonSecretAccessKey"]) emails = set([user["login"] for user in users_exists] + [user["email"] for user in users_invited]) - set([user["email"] for user in users_not_to_send]) for email in emails: if "@" in email: print email sender.sendEmail(settings["email_sender"], email, msg)
def test_csv_bom(self): with open(os.path.join(os.path.dirname(__file__), 'csv_translations', 'fr_FR.csv'), 'rb') as f: char_data = to_unicode(f.read()) # Re-encode our input data (which is utf-8 without BOM) in # encodings that use the BOM and ensure that we can still load # it. Note that utf-16-le and utf-16-be do not write a BOM, # so we only test whichver variant is native to our platform. for encoding in ['utf-8-sig', 'utf-16']: tmpdir = tempfile.mkdtemp() try: with open(os.path.join(tmpdir, 'fr_FR.csv'), 'wb') as f: f.write(char_data.encode(encoding)) tornado.locale.load_translations(tmpdir) locale = tornado.locale.get('fr_FR') self.assertIsInstance(locale, tornado.locale.CSVLocale) self.assertEqual(locale.translate("school"), u"\u00e9cole") finally: shutil.rmtree(tmpdir)
def test_csv(self): tornado.locale.load_translations( os.path.join(os.path.dirname(__file__), 'csv_translations')) locale = tornado.locale.get("fr_FR") self.assertTrue(isinstance(locale, tornado.locale.CSVLocale)) self.assertEqual(locale.translate("school"), u"\u00e9cole")
def format_token_rules(tokens, t_type=None, locale=None): """Return a human-readable string describing the given token rules tokens (dict): all the token rules (as seen in Task or Contest), without the "token_" prefix. t_type (str): the type of tokens the string should refer to (can be "contest" to mean contest-tokens, "task" to mean task-tokens, any other value to mean normal tokens). locale (tornado.locale.Locale): the locale to be used. return (string): localized string describing the rules. """ if locale is None: locale = tornado.locale.get() if t_type == "contest": tokens["type_none"] = locale.translate("no contest-tokens") tokens["type_s"] = locale.translate("contest-token") tokens["type_pl"] = locale.translate("contest-tokens") elif t_type == "task": tokens["type_none"] = locale.translate("no task-tokens") tokens["type_s"] = locale.translate("task-token") tokens["type_pl"] = locale.translate("task-tokens") else: tokens["type_none"] = locale.translate("no tokens") tokens["type_s"] = locale.translate("token") tokens["type_pl"] = locale.translate("tokens") tokens["min_interval"] = int(tokens["min_interval"].total_seconds()) tokens["gen_time"] = int(tokens["gen_time"].total_seconds() / 60) result = "" if tokens['initial'] is None: # note: we are sure that this text will only be displayed in task # pages because if tokens are disabled for the whole contest they # don't appear anywhere in CWS result += locale.translate( "You don't have %(type_pl)s available for this task.") % tokens elif tokens['gen_time'] == 0 and tokens['gen_number'] > 0: result += locale.translate("You have infinite %(type_pl)s.") % tokens result += " " if tokens['min_interval'] > 0: if tokens['min_interval'] == 1: result += locale.translate( "You can use a %(type_s)s every second.") % tokens else: result += locale.translate( "You can use a %(type_s)s every %(min_interval)d seconds." ) % tokens else: result += locale.translate( "You have no limitations on how you use them.") % tokens else: if tokens['initial'] == 0: result += locale.translate( "You start with %(type_none)s.") % tokens elif tokens['initial'] == 1: result += locale.translate( "You start with one %(type_s)s.") % tokens else: result += locale.translate( "You start with %(initial)d %(type_pl)s.") % tokens result += " " if tokens['gen_time'] > 0 and tokens['gen_number'] > 0: if tokens['gen_time'] == 1: result += locale.translate("Every minute ") % tokens else: result += locale.translate( "Every %(gen_time)d minutes ") % tokens if tokens['max'] is not None: if tokens['gen_number'] == 1: result += locale.translate( "you get another %(type_s)s, ") % tokens else: result += locale.translate( "you get %(gen_number)d other %(type_pl)s, ") % tokens if tokens['max'] == 1: result += locale.translate( "up to a maximum of one %(type_s)s.") % tokens else: result += locale.translate( "up to a maximum of %(max)d %(type_pl)s.") % tokens else: if tokens['gen_number'] == 1: result += locale.translate( "you get another %(type_s)s.") % tokens else: result += locale.translate( "you get %(gen_number)d other %(type_pl)s.") % tokens else: result += locale.translate( "You don't get other %(type_pl)s.") % tokens result += " " if tokens['min_interval'] > 0 and tokens['total'] is not None: if tokens['min_interval'] == 1: result += locale.translate( "You can use a %(type_s)s every second ") % tokens else: result += locale.translate( "You can use a %(type_s)s every %(min_interval)d seconds " ) % tokens if tokens['total'] == 1: result += locale.translate( "and no more than one %(type_s)s in total.") % tokens else: result += locale.translate( "and no more than %(total)d %(type_pl)s in total." ) % tokens elif tokens['min_interval'] > 0: if tokens['min_interval'] == 1: result += locale.translate( "You can use a %(type_s)s every second.") % tokens else: result += locale.translate( "You can use a %(type_s)s every %(min_interval)d seconds." ) % tokens elif tokens['total'] is not None: if tokens['total'] == 1: result += locale.translate( "You can use no more than one %(type_s)s in total." ) % tokens else: result += locale.translate( "You can use no more than %(total)d %(type_pl)s in total." ) % tokens else: result += locale.translate( "You have no limitations on how you use them.") % tokens return result
def _trans(s, locale): locale = tornado.locale.get(locale) s = locale.translate(s).strip("\"") return s
def format_token_rules(tokens, t_type=None, locale=None): """Return a human-readable string describing the given token rules tokens (dict): all the token rules (as seen in Task or Contest), without the "token_" prefix. t_type (str): the type of tokens the string should refer to (can be "contest" to mean contest-tokens, "task" to mean task-tokens, any other value to mean normal tokens). locale (tornado.locale.Locale): the locale to be used. return (string): localized string describing the rules. """ if locale is None: locale = tornado.locale.get() if t_type == "contest": tokens["type_none"] = locale.translate("no contest-tokens") tokens["type_s"] = locale.translate("contest-token") tokens["type_pl"] = locale.translate("contest-tokens") elif t_type == "task": tokens["type_none"] = locale.translate("no task-tokens") tokens["type_s"] = locale.translate("task-token") tokens["type_pl"] = locale.translate("task-tokens") else: tokens["type_none"] = locale.translate("no tokens") tokens["type_s"] = locale.translate("token") tokens["type_pl"] = locale.translate("tokens") tokens["min_interval"] = int(tokens["min_interval"].total_seconds()) tokens["gen_time"] = int(tokens["gen_time"].total_seconds() / 60) result = "" if tokens['initial'] is None: # note: we are sure that this text will only be displayed in task # pages because if tokens are disabled for the whole contest they # don't appear anywhere in CWS result += locale.translate("You don't have %(type_pl)s available for this task.") % tokens elif tokens['gen_time'] == 0 and tokens['gen_number'] > 0: result += locale.translate("You have infinite %(type_pl)s.") % tokens result += " " if tokens['min_interval'] > 0: if tokens['min_interval'] == 1: result += locale.translate("You can use a %(type_s)s every second.") % tokens else: result += locale.translate("You can use a %(type_s)s every %(min_interval)d seconds.") % tokens else: result += locale.translate("You have no limitations on how you use them.") % tokens else: if tokens['initial'] == 0: result += locale.translate("You start with %(type_none)s.") % tokens elif tokens['initial'] == 1: result += locale.translate("You start with one %(type_s)s.") % tokens else: result += locale.translate("You start with %(initial)d %(type_pl)s.") % tokens result += " " if tokens['gen_time'] > 0 and tokens['gen_number'] > 0: if tokens['gen_time'] == 1: result += locale.translate("Every minute ") % tokens else: result += locale.translate("Every %(gen_time)d minutes ") % tokens if tokens['max'] is not None: if tokens['gen_number'] == 1: result += locale.translate("you get another %(type_s)s, ") % tokens else: result += locale.translate("you get %(gen_number)d other %(type_pl)s, ") % tokens if tokens['max'] == 1: result += locale.translate("up to a maximum of one %(type_s)s.") % tokens else: result += locale.translate("up to a maximum of %(max)d %(type_pl)s.") % tokens else: if tokens['gen_number'] == 1: result += locale.translate("you get another %(type_s)s.") % tokens else: result += locale.translate("you get %(gen_number)d other %(type_pl)s.") % tokens else: result += locale.translate("You don't get other %(type_pl)s.") % tokens result += " " if tokens['min_interval'] > 0 and tokens['total'] is not None: if tokens['min_interval'] == 1: result += locale.translate("You can use a %(type_s)s every second ") % tokens else: result += locale.translate("You can use a %(type_s)s every %(min_interval)d seconds ") % tokens if tokens['total'] == 1: result += locale.translate("and no more than one %(type_s)s in total.") % tokens else: result += locale.translate("and no more than %(total)d %(type_pl)s in total.") % tokens elif tokens['min_interval'] > 0: if tokens['min_interval'] == 1: result += locale.translate("You can use a %(type_s)s every second.") % tokens else: result += locale.translate("You can use a %(type_s)s every %(min_interval)d seconds.") % tokens elif tokens['total'] is not None: if tokens['total'] == 1: result += locale.translate("You can use no more than one %(type_s)s in total.") % tokens else: result += locale.translate("You can use no more than %(total)d %(type_pl)s in total.") % tokens else: result += locale.translate("You have no limitations on how you use them.") % tokens return result