Example #1
0
def _CheckGnOutputsRange(gn_lines, start, end, wanted_locales):
  if not _CheckGnOutputsRangeForLocalizedStrings(gn_lines, start, end):
    return []

  errors = []
  locales = set()
  for pos in xrange(start, end):
    line = gn_lines[pos]
    android_locale = _GetAndroidGnOutputLocale(line)
    assert android_locale != None
    cr_locale = resource_utils.ToChromiumLocaleName(android_locale)
    if cr_locale in locales:
      errors.append('%s: Redefinition of output for "%s" locale' %
                    (pos + 1, android_locale))
    locales.add(cr_locale)

  extra_locales = locales.difference(wanted_locales)
  if extra_locales:
    errors.append('%d-%d: Extra locales: %s' % (start + 1, end + 1,
                                                sorted(extra_locales)))

  missing_locales = wanted_locales.difference(locales)
  if missing_locales:
    errors.append('%d-%d: Missing locales: %s' % (start + 1, end + 1,
                                                  sorted(missing_locales)))

  return errors
Example #2
0
def _RenameLocaleResourceDirs(resource_dirs):
    """Rename locale resource directories into standard names when necessary.

  This is necessary to deal with the fact that older Android releases only
  support ISO 639-1 two-letter codes, and sometimes even obsolete versions
  of them.

  In practice it means:
    * 3-letter ISO 639-2 qualifiers are renamed under a corresponding
      2-letter one. E.g. for Filipino, strings under values-fil/ will be moved
      to a new corresponding values-tl/ sub-directory.

    * Modern ISO 639-1 codes will be renamed to their obsolete variant
      for Indonesian, Hebrew and Yiddish (e.g. 'values-in/ -> values-id/).

    * Norwegian macrolanguage strings will be renamed to Bokmål (main
      Norway language). See http://crbug.com/920960. In practice this
      means that 'values-no/ -> values-nb/' unless 'values-nb/' already
      exists.

    * BCP 47 langauge tags will be renamed to an equivalent ISO 639-1
      locale qualifier if possible (e.g. 'values-b+en+US/ -> values-en-rUS').
      Though this is not necessary at the moment, because no third-party
      package that Chromium links against uses these for the current list of
      supported locales, this may change when the list is extended in the
      future).

  Args:
    resource_dirs: list of top-level resource directories.
  Returns:
    A dictionary mapping renamed paths to their original location
    (e.g. '.../values-tl/strings.xml' -> ' .../values-fil/strings.xml').
  """
    renamed_paths = dict()
    for resource_dir in resource_dirs:
        for path in _IterFiles(resource_dir):
            locale = resource_utils.FindLocaleInStringResourceFilePath(path)
            if not locale:
                continue
            cr_locale = resource_utils.ToChromiumLocaleName(locale)
            if not cr_locale:
                continue  # Unsupported Android locale qualifier!?
            locale2 = resource_utils.ToAndroidLocaleName(cr_locale)
            if locale != locale2:
                path2 = path.replace('/values-%s/' % locale,
                                     '/values-%s/' % locale2)
                if path == path2:
                    raise Exception(
                        'Could not substitute locale %s for %s in %s' %
                        (locale, locale2, path))
                if os.path.exists(path2):
                    # This happens sometimes, e.g. some libraries provide both
                    # values-nb/ and values-no/ with the same content.
                    continue
                build_utils.MakeDirectory(os.path.dirname(path2))
                shutil.move(path, path2)
                renamed_paths[os.path.relpath(path2,
                                              resource_dir)] = os.path.relpath(
                                                  path, resource_dir)
    return renamed_paths
def _AddMissingLocalesInGnOutputs(gn_lines, wanted_locales):
    intervals = _BuildIntervalList(gn_lines, _IsAndroidGnOutputLine)
    # NOTE: Since this may insert new lines to each interval, process the
    # list in reverse order to maintain valid (start,end) positions during
    # the iteration.
    for start, end in reversed(intervals):
        if not _CheckGnOutputsRangeForLocalizedStrings(gn_lines, start, end):
            continue

        locales = set()
        for pos in xrange(start, end):
            lang = _GetAndroidGnOutputLocale(gn_lines[pos])
            locale = resource_utils.ToChromiumLocaleName(lang)
            locales.add(locale)

        missing_locales = wanted_locales.difference(locales)
        if not missing_locales:
            continue

        src_locale = 'bg'
        src_values = 'values-%s/' % resource_utils.ToAndroidLocaleName(
            src_locale)
        src_line = None
        for pos in xrange(start, end):
            if src_values in gn_lines[pos]:
                src_line = gn_lines[pos]
                break

        if not src_line:
            raise Exception('Cannot find output list item with "%s" locale' %
                            src_locale)

        line_count = end - 1
        for locale in missing_locales:
            if locale == _DEFAULT_LOCALE:
                dst_line = src_line.replace('values-%s/' % src_locale,
                                            'values/')
            else:
                dst_line = src_line.replace(
                    'values-%s/' % src_locale,
                    'values-%s/' % resource_utils.ToAndroidLocaleName(locale))
            gn_lines.insert(line_count, dst_line)
            line_count += 1

        gn_lines = _SortListSubRange(
            gn_lines, start, line_count,
            lambda line: _RE_GN_VALUES_LIST_LINE.match(line).group(1))

    return gn_lines
def _RenameLocaleResourceDirs(resource_dirs, path_info):
    """Rename locale resource directories into standard names when necessary.

  This is necessary to deal with the fact that older Android releases only
  support ISO 639-1 two-letter codes, and sometimes even obsolete versions
  of them.

  In practice it means:
    * 3-letter ISO 639-2 qualifiers are renamed under a corresponding
      2-letter one. E.g. for Filipino, strings under values-fil/ will be moved
      to a new corresponding values-tl/ sub-directory.

    * Modern ISO 639-1 codes will be renamed to their obsolete variant
      for Indonesian, Hebrew and Yiddish (e.g. 'values-in/ -> values-id/).

    * Norwegian macrolanguage strings will be renamed to Bokmal (main
      Norway language). See http://crbug.com/920960. In practice this
      means that 'values-no/ -> values-nb/' unless 'values-nb/' already
      exists.

    * BCP 47 langauge tags will be renamed to an equivalent ISO 639-1
      locale qualifier if possible (e.g. 'values-b+en+US/ -> values-en-rUS').

  Args:
    resource_dirs: list of top-level resource directories.
  """
    for resource_dir in resource_dirs:
        ignore_dirs = {}
        for path in _IterFiles(resource_dir):
            locale = resource_utils.FindLocaleInStringResourceFilePath(path)
            if not locale:
                continue
            cr_locale = resource_utils.ToChromiumLocaleName(locale)
            if not cr_locale:
                continue  # Unsupported Android locale qualifier!?
            locale2 = resource_utils.ToAndroidLocaleName(cr_locale)
            if locale != locale2:
                path2 = path.replace('/values-%s/' % locale,
                                     '/values-%s/' % locale2)
                if path == path2:
                    raise Exception(
                        'Could not substitute locale %s for %s in %s' %
                        (locale, locale2, path))

                # Ignore rather than rename when the destination resources config
                # already exists.
                # e.g. some libraries provide both values-nb/ and values-no/.
                # e.g. material design provides:
                # * res/values-rUS/values-rUS.xml
                # * res/values-b+es+419/values-b+es+419.xml
                config_dir = os.path.dirname(path2)
                already_has_renamed_config = ignore_dirs.get(config_dir)
                if already_has_renamed_config is None:
                    # Cache the result of the first time the directory is encountered
                    # since subsequent encounters will find the directory already exists
                    # (due to the rename).
                    already_has_renamed_config = os.path.exists(config_dir)
                    ignore_dirs[config_dir] = already_has_renamed_config
                if already_has_renamed_config:
                    continue

                build_utils.MakeDirectory(os.path.dirname(path2))
                shutil.move(path, path2)
                path_info.RegisterRename(os.path.relpath(path, resource_dir),
                                         os.path.relpath(path2, resource_dir))