def test_pl_po_manually(self): lang = settings.LANGUAGE_CODE invalidate_language("pl") self.assertEqual(Translation.objects.count(), 0) MasterTranslation.objects.create( language_code=lang, text="%(n)s result", plural_text="%(n)s results", ) MasterTranslation.objects.create( language_code=lang, text="cat", ) mock_file_contents = u'''# Something something # Translators list msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" "PO-Revision-Date: 2015-01-18 15:19+0000\n" "Last-Translator: Janusz Harkot <*****@*****.**>\n" "Language-Team: Polish (http://www.transifex.com/projects/p/django/language/" "pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #, python-format msgid "%(n)s result" msgid_plural "%(n)s results" msgstr[0] "%(n)s wynik" msgstr[1] "%(n)s wyniki" msgstr[2] "%(n)s wyników" #, python-format msgid "cat" msgstr "kot" ''' #msgctxt "context hint" import_translations_from_po(mock_file_contents, "pl", lang) translation.activate("pl") self.assertEqual(ngettext("%(n)s result", "", 0).decode('utf-8'), u"%(n)s wyników") self.assertEqual(ngettext("%(n)s result", "", 1).decode('utf-8'), u"%(n)s wynik") self.assertEqual(ngettext("%(n)s result", "", 2).decode('utf-8'), u"%(n)s wyniki") self.assertEqual(ngettext("%(n)s result", "", 5).decode('utf-8'), u"%(n)s wyników") # Singlar translation test self.assertEqual(gettext("cat"), u"kot") # This form is wrong because po don't support the fraction plural form! self.assertEqual(ngettext("%(n)s result", "", 0.5).decode('utf-8'), u"%(n)s wyników") # u") self.assertEqual(get_plural_index("pl", 0), cldr.MANY) self.assertEqual(get_plural_index("pl", 1), cldr.ONE) self.assertEqual(get_plural_index("pl", 2), cldr.FEW) self.assertEqual(get_plural_index("pl", 5), cldr.MANY) self.assertEqual(get_plural_index("pl", 1.1), cldr.OTHER)
def save(self, *args, **kwargs): assert self.text assert self.language_code # Always store the first letter for querying self.first_letter = self.text.strip()[:1] # Generate the appropriate key on creation if self._state.adding: self.pk = MasterTranslation.generate_key( self.text, self.hint, self.language_code ) # If we are adding for the first time, then create a counterpart # translation for the master language. # Note that this Translation will be complete and correct only for the languages that # only require 2 plural forms - for others this language needs to be explicitly translated # or updated later. if self._state.adding: with transaction.atomic(xg=True): singular_form = get_plural_index(self.language_code, 1) plural_form = get_plural_index(self.language_code, 2) plurals = {singular_form: self.text} if self.is_plural: plurals[plural_form] = self.plural_text # if len(LANGUAGE_LOOKUPS[self.language_code].plurals_needed) > len(plurals): # FIXME: We can detect that we're dealing with a language that needs more plurals # What should we do? mark the translation as incomplete? # Don't create the translation object at all? new_trans = Translation.objects.create( master_translation=self, language_code=self.language_code, plural_texts=plurals, denorm_master_text=self.text, denorm_master_hint=self.hint ) self.translations_by_language_code[self.language_code] = new_trans.pk self.translations.add(new_trans) self.translated_into_languages = set(self.translations_by_language_code.keys()) return super(MasterTranslation, self).save(*args, **kwargs) else: # Otherwise just do a normal save self.translated_into_languages = set(self.translations_by_language_code.keys()) return super(MasterTranslation, self).save(*args, **kwargs)
def test_pl_arb_manually(self): lang = settings.LANGUAGE_CODE invalidate_language("pl") self.assertEqual(Translation.objects.count(), 0) pk1 = MasterTranslation.objects.create( language_code=lang, text="result", plural_text="results", ).pk pk2 = MasterTranslation.objects.create( language_code=lang, text="cat", ).pk data = { "@@locale": "pl", # two form isn't needed or used by the pl lookup function so it should be ignored pk1: u"{NUM, plural, one {wynik} few {wyniki} two {blabla} many {wyników} other {wyniku}}", "@" + pk1: { "context": "", "source_text": "result", "type": "text" }, pk2: u"kot", "@" + pk2: { "context": "", "source_text": "cat", "type": "text" }, } mock_file = StringIO(json.dumps(data)) import_translations_from_arb(mock_file, "pl") translation.activate("pl") self.assertEqual(ngettext("result", "", 0).decode('utf-8'), u"wyników") self.assertEqual(ngettext("result", "", 1).decode('utf-8'), u"wynik") self.assertEqual(ngettext("result", "", 2).decode('utf-8'), u"wyniki") self.assertEqual(ngettext("result", "", 5).decode('utf-8'), u"wyników") self.assertEqual( ngettext("result", "", 0.5).decode('utf-8'), u"wyniku") # Singlar translation test self.assertEqual(gettext("cat"), u"kot") self.assertEqual(get_plural_index("pl", 0), cldr.MANY) self.assertEqual(get_plural_index("pl", 1), cldr.ONE) self.assertEqual(get_plural_index("pl", 2), cldr.FEW) self.assertEqual(get_plural_index("pl", 5), cldr.MANY) self.assertEqual(get_plural_index("pl", 1.1), cldr.OTHER)
def save(self, *args, **kwargs): assert self.text assert self.language_code # Always store the first letter for querying self.first_letter = self.text[0] # Generate the appropriate key on creation if self._state.adding: self.pk = MasterTranslation.generate_key( self.text, self.hint, self.language_code ) # If we are adding for the first time, then create a counterpart # translation for the master language. # Note that this Translation will be complete and correct only for the languages that # only require 2 plural forms - for others this language needs to be explicitly translated # or updated later. if self._state.adding: with transaction.atomic(xg=True): singular_form = get_plural_index(self.language_code, 1) plural_form = get_plural_index(self.language_code, 2) plurals = {singular_form: self.text} if self.is_plural: plurals[plural_form] = self.plural_text # if len(LANGUAGE_LOOKUPS[self.language_code].plurals_needed) > len(plurals): # FIXME: We can detect that we're dealing with a language that needs more plurals # What should we do? mark the translation as incomplete? # Don't create the translation object at all? new_trans = Translation.objects.create( master_translation=self, language_code=self.language_code, plural_texts=plurals, denorm_master_text=self.text, denorm_master_hint=self.hint ) self.translations_by_language_code[self.language_code] = new_trans.pk self.translations.add(new_trans) self.translated_into_languages = set(self.translations_by_language_code.keys()) return super(MasterTranslation, self).save(*args, **kwargs) else: # Otherwise just do a normal save self.translated_into_languages = set(self.translations_by_language_code.keys()) return super(MasterTranslation, self).save(*args, **kwargs)
def text(self): singular_form = get_plural_index(self.language_code, 1) try: return self.plural_texts[singular_form] except KeyError: # Some kind of corrupt data, so just return the source language return self.denorm_master_text
def test_pl_arb_manually(self): lang = settings.LANGUAGE_CODE invalidate_language("pl") self.assertEqual(Translation.objects.count(), 0) pk1 = MasterTranslation.objects.create( language_code=lang, text="result", plural_text="results", ).pk pk2 = MasterTranslation.objects.create( language_code=lang, text="cat", ).pk data = { "@@locale": "pl", # two form isn't needed or used by the pl lookup function so it should be ignored pk1: u"{NUM, plural, one {wynik} few {wyniki} two {blabla} many {wyników} other {wyniku}}", "@"+pk1: { "context": "", "source_text": "result", "type": "text" }, pk2: u"kot", "@"+pk2: { "context": "", "source_text": "cat", "type": "text" }, } mock_file = StringIO(json.dumps(data)) import_translations_from_arb(mock_file, "pl") translation.activate("pl") self.assertEqual(ngettext("result", "", 0).decode('utf-8'), u"wyników") self.assertEqual(ngettext("result", "", 1).decode('utf-8'), u"wynik") self.assertEqual(ngettext("result", "", 2).decode('utf-8'), u"wyniki") self.assertEqual(ngettext("result", "", 5).decode('utf-8'), u"wyników") self.assertEqual(ngettext("result", "", 0.5).decode('utf-8'), u"wyniku") # Singlar translation test self.assertEqual(gettext("cat"), u"kot") self.assertEqual(get_plural_index("pl", 0), cldr.MANY) self.assertEqual(get_plural_index("pl", 1), cldr.ONE) self.assertEqual(get_plural_index("pl", 2), cldr.FEW) self.assertEqual(get_plural_index("pl", 5), cldr.MANY) self.assertEqual(get_plural_index("pl", 1.1), cldr.OTHER)
def validate_translation_texts(trans, master=None): if not master: master = trans.master_translation msgs = [] singular_form = get_plural_index(trans.language_code, 1) for key, msg in trans.plural_texts.items(): if not key.startswith("="): compare_to = master.text if key == singular_form else master.plural_text msgs.extend(compare_format_strings(compare_to, msg)) return msgs
def _get_trans(text, hint, count=1, language_override=None): from django.utils.translation import get_language language_code = language_override or get_language() # With translations deactivated return the original text # Currently this will be the singular form even for pluralized messages if language_code is None: return unicode(text) assert(text is not None) # If no text was specified, there won't be a master translation for it # so just return the empty text (we check for not if not text: return u"" forms = TRANSLATION_CACHE.get_translation(text, hint, language_code) if not forms: # We have no translation for this text. logger.debug( "Found string not translated into %s so falling back to default, string was %s", language_code, text ) # This unicode() call is important. If we are here it means that we do not have a # translation for this text string, so we want to just return the default text, which is # the `text` variable. But if this variable has come from a `{% trans %}` tag, then it will # have been through django.template.base.Variable.__init__, which makes the assumption that # any string literal defined in a template is safe, and therefore it calls mark_safe() on # it. Fluent's `trans` tag deliberately does NOT make the assumption that string literals # defined inside it are safe (because we don't want to send pre-escaped text to translators) # and therefore we must remove the assumption that the string is safe. Calling unicode() on # it turns it from a SafeText object back to a normal unicode object. return unicode(text) plural_index = get_plural_index(language_code, count) # Fall back to singular form if the correct plural doesn't exist. This will happen until all languages have been re-uploaded. if plural_index in forms: return forms[plural_index] singular_index = get_plural_index(language_code, 1) return forms[singular_index]
def import_icu_message(msg, language=None): """ Decode the ICU message into a plurals dict. """ if RE_ICU_MSG.match(msg): plural_form = get_plural_index(language, 1) if language else ONE return {plural_form: _icu_decode(msg)} # If the msg doesn't match a direct singular translation, attempt to decode as a plurals dict: match = RE_ICU_PLURAL_MSG.match(msg) data = match and match.group('plurals') if not data: raise ValueError('Incorrect ICU translation encoding') return _decode_icu_plurals(data)
def test_plural_rules(self): """ Test all example values from plurals.xml against our pluralization rules.""" for example in self.examples: for locale in example['locales']: for keyword, values in example.items(): if keyword == 'locales': continue for v in values: computed = get_plural_index(locale, v) self.assertEqual(keyword, computed, "For language %s (%s) value: %r, expected: %s, got: %s" % (locale, ', '.join(example['locales']), v, keyword, computed))
def _get_trans(text, hint, count=1, language_override=None): from django.utils.translation import get_language language_code = language_override or get_language() forms = TRANSLATION_CACHE.get_translation(text, hint, language_code) if not forms: logger.debug( "Found string not translated into %s so falling back to default, string was %s", language_code, text ) return text plural_index = get_plural_index(language_code, count) # Fall back to singular form if the correct plural doesn't exist. This will happen until all languages have been re-uploaded. if plural_index in forms: return forms[plural_index] singular_index = get_plural_index(language_code, 1) return forms[singular_index]
def import_icu_message(msg, language=None): """ Decode the ICU message into a plurals dict. """ if RE_ICU_MSG.match(msg): plural_form = get_plural_index(language, 1) if language else ONE return {plural_form: _icu_decode(msg)} # If the msg doesn't match a direct singular translation, attempt to decode as a plurals dict: match = RE_ICU_PLURAL_MSG.match(msg) data = match and match.group("plurals") if not data: raise ValueError("Incorrect ICU translation encoding") return _decode_icu_plurals(data)
def _get_trans(text, hint, count=1, language_override=None): from django.utils.translation import get_language language_code = language_override or get_language() forms = TRANSLATION_CACHE.get_translation(text, hint, language_code) if not forms: logger.debug( "Found string not translated into %s so falling back to default, string was %s", language_code, text) return text plural_index = get_plural_index(language_code, count) # Fall back to singular form if the correct plural doesn't exist. This will happen until all languages have been re-uploaded. if plural_index in forms: return forms[plural_index] singular_index = get_plural_index(language_code, 1) return forms[singular_index]
def _get_trans(text, hint, count=1, language_override=None): from django.utils.translation import get_language language_code = language_override or get_language() # With translations deactivated return the original text # Currently this will be the singular form even for pluralized messages if language_code is None: return unicode(text) assert (text is not None) # If no text was specified, there won't be a master translation for it # so just return the empty text (we check for not if not text: return u"" forms = TRANSLATION_CACHE.get_translation(text, hint, language_code) if not forms: # We have no translation for this text. logger.debug( "Found string not translated into %s so falling back to default, string was %s", language_code, text) # This unicode() call is important. If we are here it means that we do not have a # translation for this text string, so we want to just return the default text, which is # the `text` variable. But if this variable has come from a `{% trans %}` tag, then it will # have been through django.template.base.Variable.__init__, which makes the assumption that # any string literal defined in a template is safe, and therefore it calls mark_safe() on # it. Fluent's `trans` tag deliberately does NOT make the assumption that string literals # defined inside it are safe (because we don't want to send pre-escaped text to translators) # and therefore we must remove the assumption that the string is safe. Calling unicode() on # it turns it from a SafeText object back to a normal unicode object. return unicode(text) plural_index = get_plural_index(language_code, count) # Fall back to singular form if the correct plural doesn't exist. This will happen until all languages have been re-uploaded. if plural_index in forms: return forms[plural_index] singular_index = get_plural_index(language_code, 1) return forms[singular_index]
def test_plural_rules(self): """ Test all example values from plurals.xml against our pluralization rules.""" for example in self.examples: for locale in example['locales']: for keyword, values in example.items(): if keyword == 'locales': continue for v in values: computed = get_plural_index(locale, v) self.assertEqual( keyword, computed, "For language %s (%s) value: %r, expected: %s, got: %s" % (locale, ', '.join( example['locales']), v, keyword, computed))
def text(self, value): singular_form = get_plural_index(self.language_code, 1) self.plural_texts[singular_form] = value
def test_pl_po_manually(self): lang = settings.LANGUAGE_CODE invalidate_language("pl") self.assertEqual(Translation.objects.count(), 0) MasterTranslation.objects.create( language_code=lang, text="%(n)s result", plural_text="%(n)s results", ) MasterTranslation.objects.create( language_code=lang, text="cat", ) mock_file_contents = u'''# Something something # Translators list msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" "PO-Revision-Date: 2015-01-18 15:19+0000\n" "Last-Translator: Janusz Harkot <*****@*****.**>\n" "Language-Team: Polish (http://www.transifex.com/projects/p/django/language/" "pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #, python-format msgid "%(n)s result" msgid_plural "%(n)s results" msgstr[0] "%(n)s wynik" msgstr[1] "%(n)s wyniki" msgstr[2] "%(n)s wyników" #, python-format msgid "cat" msgstr "kot" ''' #msgctxt "context hint" import_translations_from_po(mock_file_contents, "pl", lang) translation.activate("pl") self.assertEqual( ngettext("%(n)s result", "", 0).decode('utf-8'), u"%(n)s wyników") self.assertEqual( ngettext("%(n)s result", "", 1).decode('utf-8'), u"%(n)s wynik") self.assertEqual( ngettext("%(n)s result", "", 2).decode('utf-8'), u"%(n)s wyniki") self.assertEqual( ngettext("%(n)s result", "", 5).decode('utf-8'), u"%(n)s wyników") # Singlar translation test self.assertEqual(gettext("cat"), u"kot") # This form is wrong because po don't support the fraction plural form! self.assertEqual( ngettext("%(n)s result", "", 0.5).decode('utf-8'), u"%(n)s wyników") # u") self.assertEqual(get_plural_index("pl", 0), cldr.MANY) self.assertEqual(get_plural_index("pl", 1), cldr.ONE) self.assertEqual(get_plural_index("pl", 2), cldr.FEW) self.assertEqual(get_plural_index("pl", 5), cldr.MANY) self.assertEqual(get_plural_index("pl", 1.1), cldr.OTHER)