summaryrefslogtreecommitdiff
path: root/blockly/i18n/json_to_js.py
diff options
context:
space:
mode:
Diffstat (limited to 'blockly/i18n/json_to_js.py')
-rwxr-xr-xblockly/i18n/json_to_js.py185
1 files changed, 185 insertions, 0 deletions
diff --git a/blockly/i18n/json_to_js.py b/blockly/i18n/json_to_js.py
new file mode 100755
index 0000000..f8c20f6
--- /dev/null
+++ b/blockly/i18n/json_to_js.py
@@ -0,0 +1,185 @@
+#!/usr/bin/python
+
+# Converts .json files into .js files for use within Blockly apps.
+#
+# Copyright 2013 Google Inc.
+# https://developers.google.com/blockly/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import codecs # for codecs.open(..., 'utf-8')
+import glob
+import json # for json.load()
+import os # for os.path()
+import subprocess # for subprocess.check_call()
+from common import InputError
+from common import read_json_file
+
+
+# Store parsed command-line arguments in global variable.
+args = None
+
+
+def _create_xlf(target_lang):
+ """Creates a <target_lang>.xlf file for Soy.
+
+ Args:
+ target_lang: The ISO 639 language code for the target language.
+ This is used in the name of the file and in the metadata.
+
+ Returns:
+ A pointer to a file to which the metadata has been written.
+
+ Raises:
+ IOError: An error occurred while opening or writing the file.
+ """
+ filename = os.path.join(os.curdir, args.output_dir, target_lang + '.xlf')
+ out_file = codecs.open(filename, 'w', 'utf-8')
+ out_file.write("""<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file original="SoyMsgBundle"
+ datatype="x-soy-msg-bundle"
+ xml:space="preserve"
+ source-language="{0}"
+ target-language="{1}">
+ <body>""".format(args.source_lang, target_lang))
+ return out_file
+
+
+def _close_xlf(xlf_file):
+ """Closes a <target_lang>.xlf file created with create_xlf().
+
+ This includes writing the terminating XML.
+
+ Args:
+ xlf_file: A pointer to a file created by _create_xlf().
+
+ Raises:
+ IOError: An error occurred while writing to or closing the file.
+ """
+ xlf_file.write("""
+ </body>
+ </file>
+</xliff>
+""")
+ xlf_file.close()
+
+
+def _process_file(path_to_json, target_lang, key_dict):
+ """Creates an .xlf file corresponding to the specified .json input file.
+
+ The name of the input file must be target_lang followed by '.json'.
+ The name of the output file will be target_lang followed by '.js'.
+
+ Args:
+ path_to_json: Path to the directory of xx.json files.
+ target_lang: A IETF language code (RFC 4646), such as 'es' or 'pt-br'.
+ key_dict: Dictionary mapping Blockly keys (e.g., Maze.turnLeft) to
+ Closure keys (hash numbers).
+
+ Raises:
+ IOError: An I/O error occurred with an input or output file.
+ InputError: Input JSON could not be parsed.
+ KeyError: Key found in input file but not in key file.
+ """
+ keyfile = os.path.join(path_to_json, target_lang + '.json')
+ j = read_json_file(keyfile)
+ out_file = _create_xlf(target_lang)
+ for key in j:
+ if key != '@metadata':
+ try:
+ identifier = key_dict[key]
+ except KeyError, e:
+ print('Key "%s" is in %s but not in %s' %
+ (key, keyfile, args.key_file))
+ raise e
+ target = j.get(key)
+ out_file.write(u"""
+ <trans-unit id="{0}" datatype="html">
+ <target>{1}</target>
+ </trans-unit>""".format(identifier, target))
+ _close_xlf(out_file)
+
+
+def main():
+ """Parses arguments and iterates over files."""
+
+ # Set up argument parser.
+ parser = argparse.ArgumentParser(description='Convert JSON files to JS.')
+ parser.add_argument('--source_lang', default='en',
+ help='ISO 639-1 source language code')
+ parser.add_argument('--output_dir', default='generated',
+ help='relative directory for output files')
+ parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json',
+ help='relative path to input keys file')
+ parser.add_argument('--template', default='template.soy')
+ parser.add_argument('--path_to_jar',
+ default='..' + os.path.sep + 'apps' + os.path.sep
+ + '_soy',
+ help='relative path from working directory to '
+ 'SoyToJsSrcCompiler.jar')
+ parser.add_argument('files', nargs='+', help='input files')
+
+ # Initialize global variables.
+ global args
+ args = parser.parse_args()
+
+ # Make sure output_dir ends with slash.
+ if (not args.output_dir.endswith(os.path.sep)):
+ args.output_dir += os.path.sep
+
+ # Read in keys.json, mapping descriptions (e.g., Maze.turnLeft) to
+ # Closure keys (long hash numbers).
+ key_file = open(args.key_file)
+ key_dict = json.load(key_file)
+ key_file.close()
+
+ # Process each input file.
+ print('Creating .xlf files...')
+ processed_langs = []
+ if len(args.files) == 1:
+ # Windows does not expand globs automatically.
+ args.files = glob.glob(args.files[0])
+ for arg_file in args.files:
+ (path_to_json, filename) = os.path.split(arg_file)
+ if not filename.endswith('.json'):
+ raise InputError(filename, 'filenames must end with ".json"')
+ target_lang = filename[:filename.index('.')]
+ if not target_lang in ('qqq', 'keys'):
+ processed_langs.append(target_lang)
+ _process_file(path_to_json, target_lang, key_dict)
+
+ # Output command line for Closure compiler.
+ if processed_langs:
+ print('Creating .js files...')
+ processed_lang_list = ','.join(processed_langs)
+ subprocess.check_call([
+ 'java',
+ '-jar', os.path.join(args.path_to_jar, 'SoyToJsSrcCompiler.jar'),
+ '--locales', processed_lang_list,
+ '--messageFilePathFormat', args.output_dir + '{LOCALE}.xlf',
+ '--outputPathFormat', args.output_dir + '{LOCALE}.js',
+ '--srcs', args.template])
+ if len(processed_langs) == 1:
+ print('Created ' + processed_lang_list + '.js in ' + args.output_dir)
+ else:
+ print('Created {' + processed_lang_list + '}.js in ' + args.output_dir)
+
+ for lang in processed_langs:
+ os.remove(args.output_dir + lang + '.xlf')
+ print('Removed .xlf files.')
+
+
+if __name__ == '__main__':
+ main()