Home | History | Annotate | Download | only in mac
      1 #!/usr/bin/python
      2 
      3 # Copyright (c) 2009 The Chromium Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 # Usage: generate_localizer [xib_path] [output_dot_h_path] [output_dot_mm_path]
      8 #
      9 # Extracts all the localizable strings that start with "^IDS" from the given
     10 # xib file, and then generates a localizer to process those strings.
     11 
     12 import os
     13 import plistlib
     14 import subprocess
     15 import sys
     16 
     17 generate_localizer = "me"
     18 
     19 localizer_template_h = \
     20 '''//          ---------- WARNING ----------
     21 // THIS IS A GENERATED FILE, DO NOT EDIT IT DIRECTLY!
     22 //
     23 // This header includes the table used by ui_localizer.mm.  Nothing else should
     24 // be including this file.
     25 //
     26 // Generated by %(generate_localizer)s.
     27 // Generated from:
     28 //     %(xib_files)s
     29 //
     30 
     31 #ifndef UI_LOCALIZER_TABLE_H_
     32 #define UI_LOCALIZER_TABLE_H_
     33 
     34 static const UILocalizerResourceMap kUIResources[] = {
     35 %(resource_map_list)s  };
     36 static const size_t kUIResourcesSize = arraysize(kUIResources);
     37 
     38 #endif  // UI_LOCALIZER_TABLE_H_
     39 '''
     40 
     41 def xib_localizable_strings(xib_path):
     42   """Runs ibtool to extract the localizable strings data from the xib."""
     43   tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin')
     44   tool_path = os.path.join(tools_dir, 'ibtool')
     45 
     46   # Take SDKROOT out of the environment passed to ibtool. ibtool itself has
     47   # no need for it, but when ibtool runs via xcrun and Xcode isn't aware of
     48   # the SDK in use, its presence causes an error.
     49   if 'SDKROOT' in os.environ:
     50     ibtool_env = os.environ.copy()
     51     del ibtool_env['SDKROOT']
     52   else:
     53     ibtool_env = os.environ
     54 
     55   ibtool_cmd = subprocess.Popen([tool_path, '--localizable-strings', xib_path],
     56                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
     57                                 env=ibtool_env)
     58   (cmd_out, cmd_err) = ibtool_cmd.communicate()
     59   if ibtool_cmd.returncode:
     60     sys.stderr.write('%s:0: error: ibtool on "%s" failed (%d):\n%s\n' %
     61                      (generate_localizer, xib_path, ibtool_cmd.returncode,
     62                       cmd_err))
     63     return None
     64   return cmd_out
     65 
     66 def extract_resource_constants(plist_localizable_strings_dict, xib_path):
     67   """Extracts all the values that start with ^IDS from the localizable
     68   strings plist entry."""
     69   constants_list = []
     70   for item_dict in plist_localizable_strings_dict.itervalues():
     71     for item_value in item_dict.itervalues():
     72       if item_value.startswith('^IDS'):
     73         constants_list.append(item_value)
     74       elif item_value.startswith('IDS'):
     75         sys.stderr.write(
     76             '%s:0: warning: %s found a string with questionable prefix, "%s"\n'
     77             % (xib_path, generate_localizer, item_value));
     78   return constants_list
     79 
     80 def generate_file_contents(constants_list, xib_paths):
     81   """Generates the header listing the constants."""
     82   # Bounce through a set to uniq the strings, sort the list, then build the
     83   # values we need from it.
     84   constants_list = sorted(set(constants_list))
     85   constant_list_str = ''
     86   for item in constants_list:
     87     parts = item.split('$', 1)
     88     label_id = parts[0]
     89     if len(parts) == 2:
     90       label_arg_id = parts[1]
     91     else:
     92       label_arg_id = '0'
     93     constant_list_str += '    { "%s", %s, %s },\n' % \
     94         ( item, label_id[1:], label_arg_id)
     95   # Assemble the contents from the templates.
     96   values_dict = {
     97     'resource_map_list': constant_list_str,
     98     'generate_localizer': generate_localizer,
     99     'xib_files': "\n//     ".join(xib_paths),
    100   }
    101   h_file = localizer_template_h % values_dict
    102   return h_file
    103 
    104 
    105 def Main(argv=None):
    106   global generate_localizer
    107   generate_localizer = os.path.basename(argv[0])
    108 
    109   # Args
    110   if len(argv) < 3:
    111     sys.stderr.write('%s:0: error: Expected output file and then xibs\n' %
    112                      generate_localizer);
    113     return 1
    114   output_path = argv[1];
    115   xib_paths = argv[2:]
    116 
    117   full_constants_list = []
    118   for xib_path in xib_paths:
    119     # Run ibtool and convert to something Python can deal with
    120     plist_string = xib_localizable_strings(xib_path)
    121     if not plist_string:
    122       return 2
    123     plist = plistlib.readPlistFromString(plist_string)
    124 
    125     # Extract the resource constant strings
    126     localizable_strings = plist['com.apple.ibtool.document.localizable-strings']
    127     constants_list = extract_resource_constants(localizable_strings, xib_path)
    128     if not constants_list:
    129       sys.stderr.write("%s:0: warning: %s didn't find any resource strings\n" %
    130                        (xib_path, generate_localizer));
    131     full_constants_list.extend(constants_list)
    132 
    133   # Generate our file contents
    134   h_file_content = \
    135       generate_file_contents(full_constants_list, xib_paths)
    136 
    137   # Write out the file
    138   file_fd = open(output_path, 'w')
    139   file_fd.write(h_file_content)
    140   file_fd.close()
    141 
    142   return 0
    143 
    144 if __name__ == '__main__':
    145   sys.exit(Main(sys.argv))
    146