def check_variants(self, variants): # Check for duplicate variants warned = set() for left in range(len(variants) - 1): if left in warned: continue left_key = variants[left].key key_string = None for right in range(left + 1, len(variants)): if left_key.equals(variants[right].key): if key_string is None: key_string = serialize_variant_key(left_key) self.messages.append(('warning', left_key.span.start, MSGS['duplicate-variant'].format( name=key_string))) warned.add(right) self.messages.append( ('warning', variants[right].key.span.start, MSGS['duplicate-variant'].format(name=key_string))) # Check for plural categories known_plurals = plurals.get_plural(self.locale) if known_plurals: known_plurals = set(known_plurals) # Ask for known plurals, but check for plurals w/out `other`. # `other` is used for all kinds of things. check_plurals = known_plurals.copy() check_plurals.discard('other') given_plurals = set(serialize_variant_key(v.key) for v in variants) if given_plurals & check_plurals: missing_plurals = sorted(known_plurals - given_plurals) if missing_plurals: self.messages.append( ('warning', variants[0].key.span.start, MSGS['missing-plural'].format( categories=', '.join(missing_plurals))))
def __init__( self, lang, reference_dir, localization_dir, enforce_translated=False ): self.fluent_parser = FluentParser(with_spans=False) self.fluent_serializer = FluentSerializer() # An iterable of plural category names relevant to the context's # language. E.g. ('one', 'other') for English. self.plural_categories = get_plural(lang) if self.plural_categories is None: logger = logging.getLogger('migrate') logger.warning( 'Plural rule for "{}" is not defined in ' 'compare-locales'.format(lang)) self.plural_categories = ('one', 'other') self.enforce_translated = enforce_translated # Parsed input resources stored by resource path. self.reference_resources = {} self.localization_resources = {} self.target_resources = {} # An iterable of `FTL.Message` objects some of whose nodes can be the # transform operations. self.transforms = {} # The evaluator instance is an AST transformer capable of walking an # AST hierarchy and evaluating nodes which are migration Transforms. self.evaluator = Evaluator(self)
def check_plural(self, refValue, l10nValue): '''Check for the stringbundle plurals logic. The common variable pattern is #1. ''' known_plurals = plurals.get_plural(self.locale) if known_plurals: expected_forms = len(known_plurals) found_forms = l10nValue.count(';') + 1 msg = 'expecting {} plurals, found {}'.format( expected_forms, found_forms) if expected_forms > found_forms: yield ('warning', 0, msg, 'plural') if expected_forms < found_forms: yield ('warning', 0, msg, 'plural') pats = set(int(m.group(1)) for m in re.finditer('#([0-9]+)', refValue)) if len(pats) == 0: return lpats = set( int(m.group(1)) for m in re.finditer('#([0-9]+)', l10nValue)) if pats - lpats: yield ('warning', 0, 'not all variables used in l10n', 'plural') return if lpats - pats: yield ('error', 0, 'unreplaced variables in l10n', 'plural')