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
12import os
13import plistlib
14import subprocess
15import sys
16
17generate_localizer = "me"
18
19localizer_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
34static const UILocalizerResourceMap kUIResources[] = {
35%(resource_map_list)s  };
36static const size_t kUIResourcesSize = arraysize(kUIResources);
37
38#endif  // UI_LOCALIZER_TABLE_H_
39'''
40
41def 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
66def 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
80def 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
105def 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
144if __name__ == '__main__':
145  sys.exit(Main(sys.argv))
146