library/scripts/string_pack_config.py (85 lines of code) (raw):

# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. # # This source code is licensed under the Apache 2.0 license found in # the LICENSE file in the root directory of this source tree. import enum import json import os def load_config( config_json_dict=None, config_json_file_path=None, skip_default_config=False ): if ( config_json_dict is None and config_json_file_path is None and skip_default_config ): raise ValueError( "Please specify at least one type for loading StringPackConfig." ) sp_config = StringPackConfig() if not skip_default_config: default_config_json_file_path = os.path.join( os.path.dirname(__file__), "default_config.json" ) sp_config.load_from_file(default_config_json_file_path) if config_json_file_path is not None: sp_config.load_from_file(config_json_file_path) if config_json_dict is not None: sp_config.load_from_dict(config_json_dict) return sp_config def is_valid_language_qualifier(resource_qualifier): if len(resource_qualifier) == 2: # language only, e.g.: en return True if len(resource_qualifier) == 6 and resource_qualifier[2:4] == "-r": # language with region. e.g.: fr-rCA return True if resource_qualifier.startswith("b+") and "-" not in resource_qualifier: # special language: e.g.: b+es+419 return True return False class LanguageHandlingCase(enum.Enum): """Determine how should string packs handles strings for that language""" # Keep original file in project, don't pack them. This could happen for non-language qualifier, e.g. values-land. KEEP_ORIGINAL = 0 # Pack them at eventually, so move the string resources to intermediate file PACK = 1 # Remove the strings from original resource file, but don't move to intermediate file # See StringPackConfig.languages_to_drop DROP = 2 class StringPackConfig: """ Configurations for running string packs scripts. This provides the configuration information for string pack scripts to generate the intermediate files, and save final content at the right place. """ FIELDS_TO_OVERRIDE = [ "module", "original_resources_directories", "find_resource_files_command", "languages_to_pack", "languages_to_drop", "assets_directory", "pack_ids_class_file_path", "pack_id_mapping", "pack_scripts_directory", ] def __init__(self): # The project module that string packs are used for. self.module = None # The directories above the Android resources directories, where the script can find values/strings.xml and values-xx/ directories. # (i.e. app/src/main) # These directories will also hold the files of the packable strings. # FIND operation checks each directory's res subdirectory for values/strings.xml and values-xx/.strings.xml files. The ids are stored in pack_ids_class_file_path. # MOVE operation moves packable strings found in FIND to the directory's string-packs/strings subdirectory. # PACK operation packs the files in the directory's string-packs/strings subdirectory into .pack files in assets_directory. self.original_resources_directories = [] # Executable command line that returns all resource files for parsing movable strings. self.find_resource_files_command = None # List of languages that need to be packed, or ["*"] means all languages. self.languages_to_pack = [] # List of languages that don't need to be packed, and they could be safely removed. # e.g.: "zh-rTW" could be drop if "zh-rHK" is set the same, the app would pick it correctly. self.languages_to_drop = [] # The full class name of custom widgets that are already using StringPack resources reader. self.safe_widget_classes = set() # The assets directory where to save the generated string pack files. self.assets_directory = None # File path to the class where stores the map from android string key to pack id. self.pack_ids_class_file_path = None # A dictionary that maps a specific language to its pack ID. The default pack ID is the language code, but the # app may decide to pack similar languages to one pack file. # For example, it may save space to pack Czech and Slovak in one pack file, assuming the app knows where to # look for them. self.pack_id_mapping = {} # The directory that holds all the python scripts self.pack_scripts_directory = None def load_from_file(self, config_json_file_path): """Load configuration from json file.""" with open(config_json_file_path) as file_content: config_json_dict = json.load(file_content) self.load_from_dict(config_json_dict) def load_from_dict(self, config_dict): """Load configuration from a dictionary which servers as json. All configuration values would be overridden with the value that provided in config_json, except `safe_widget_classes` which new widget class names would be append to it. """ for field in StringPackConfig.FIELDS_TO_OVERRIDE: if field in config_dict: setattr(self, field, config_dict[field]) # Append instead of override if "safe_widget_classes" in config_dict: self.safe_widget_classes.update(config_dict["safe_widget_classes"]) return self def get_default_string_files(self): return [ os.path.join(source_directory, "res", "values", "strings.xml") for source_directory in self.original_resources_directories ] def get_handling_case(self, resource_qualifier): """Determine how to handle the string for given resource qualifier if it's a language qualifier.""" if resource_qualifier in self.languages_to_drop: return LanguageHandlingCase.DROP if self.languages_to_pack == ["*"]: # Match all valid language if is_valid_language_qualifier(resource_qualifier): return LanguageHandlingCase.PACK elif resource_qualifier in self.languages_to_pack: return LanguageHandlingCase.PACK return LanguageHandlingCase.KEEP_ORIGINAL