From dc94522ce25015c7542036162446ae624ed658dd Mon Sep 17 00:00:00 2001 From: Sergey Pisarchik Date: Fri, 16 May 2014 16:10:20 +0300 Subject: [PATCH] [tools] Add tizen support to twine. --- tools/twine/lib/twine/formatters.rb | 3 +- tools/twine/lib/twine/formatters/tizen.rb | 175 ++++++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 tools/twine/lib/twine/formatters/tizen.rb diff --git a/tools/twine/lib/twine/formatters.rb b/tools/twine/lib/twine/formatters.rb index 50ba4805ff..a5e9fc844a 100644 --- a/tools/twine/lib/twine/formatters.rb +++ b/tools/twine/lib/twine/formatters.rb @@ -5,9 +5,10 @@ require 'twine/formatters/flash' require 'twine/formatters/gettext' require 'twine/formatters/jquery' require 'twine/formatters/django' +require 'twine/formatters/tizen' module Twine module Formatters - FORMATTERS = [Formatters::Apple, Formatters::Android, Formatters::Gettext, Formatters::JQuery, Formatters::Flash, Formatters::Django] + FORMATTERS = [Formatters::Apple, Formatters::Android, Formatters::Gettext, Formatters::JQuery, Formatters::Flash, Formatters::Django, Formatters::Tizen] end end diff --git a/tools/twine/lib/twine/formatters/tizen.rb b/tools/twine/lib/twine/formatters/tizen.rb new file mode 100644 index 0000000000..d190223b43 --- /dev/null +++ b/tools/twine/lib/twine/formatters/tizen.rb @@ -0,0 +1,175 @@ +# encoding: utf-8 +require 'cgi' +require 'rexml/document' + +module Twine + module Formatters + class Tizen < Abstract + FORMAT_NAME = 'tizen' + EXTENSION = '.xml' + DEFAULT_FILE_NAME = 'strings.xml' + LANG_CODES = Hash[ + 'eng-GB' => 'en', + 'rus-RU' => 'ru', + 'fra-FR' => 'fr', + 'deu-DE' => 'de', + 'spa-ES' => 'es', + 'ita-IT' => 'it', + 'ces-CZ' => 'cs', + 'pol-PL' => 'pl', + 'por-PT' => 'pt', + 'ukr-UA' => 'uk' + ] + DEFAULT_LANG_CODES = Hash[ + ] + + def self.can_handle_directory?(path) + Dir.entries(path).any? { |item| /^values.*$/.match(item) } + end + + def default_file_name + return DEFAULT_FILE_NAME + end + + def write_all_files(path) + if !File.directory?(path) + raise Twine::Error.new("Directory does not exist: #{path}") + end + + langs_written = [] + Dir.foreach(path) do |item| + if item == "." or item == ".." + next + end + item = File.join(path, item) + if !File.directory?(item) + lang = determine_language_given_path(item) + if lang + write_file(item, lang) + langs_written << lang + end + end + end + if langs_written.empty? + raise Twine::Error.new("Failed to genertate any files: No languages found at #{path}") + end + end + + def determine_language_given_path(path) + path_arr = path.split(File::SEPARATOR) + path_arr.each do |segment| + match = /^(.*-.*)\.xml$/.match(segment) + if match + lang = match[1] + lang = LANG_CODES.fetch(lang, nil) + return lang + end + end + return + end + + def read_file(path, lang) + resources_regex = /]*)>(.*)<\/resources>/m + key_regex = // + comment_regex = // + value_regex = /(.*)<\/string>/ + key = nil + value = nil + comment = nil + + File.open(path, 'r:UTF-8') do |f| + content_match = resources_regex.match(f.read) + if content_match + for line in content_match[1].split(/\r?\n/) + key_match = key_regex.match(line) + if key_match + key = key_match[1] + value_match = value_regex.match(line) + if value_match + value = value_match[1] + value = CGI.unescapeHTML(value) + value.gsub!('\\\'', '\'') + value.gsub!('\\"', '"') + value = iosify_substitutions(value) + value.gsub!(/(\\u0020)*|(\\u0020)*\z/) { |spaces| ' ' * (spaces.length / 6) } + else + value = "" + end + set_translation_for_key(key, lang, value) + if comment and comment.length > 0 and !comment.start_with?("SECTION:") + set_comment_for_key(key, comment) + end + comment = nil + end + + comment_match = comment_regex.match(line) + if comment_match + comment = comment_match[1] + end + end + end + end + end + + def write_file(path, lang) + default_lang = nil + if DEFAULT_LANG_CODES.has_key?(lang) + default_lang = DEFAULT_LANG_CODES[lang] + end + File.open(path, 'w:UTF-8') do |f| + f.puts "\n\n\n" + f.write '' + @strings.sections.each do |section| + printed_section = false + section.rows.each do |row| + if row.matches_tags?(@options[:tags], @options[:untagged]) + if !printed_section + f.puts '' + if section.name && section.name.length > 0 + section_name = section.name.gsub('--', '—') + f.puts "\t" + end + printed_section = true + end + + key = row.key + + value = row.translated_string_for_lang(lang, default_lang) + if !value && @options[:include_untranslated] + value = row.translated_string_for_lang(@strings.language_codes[0]) + end + + if value # if values is nil, there was no appropriate translation, so let Tizen handle the defaulting + value = String.new(value) # use a copy to prevent modifying the original + + # Tizen enforces the following rules on the values + # 1) apostrophes and quotes must be escaped with a backslash + value.gsub!('\'', '\\\\\'') + value.gsub!('"', '\\\\"') + # 2) HTML escape the string + value = CGI.escapeHTML(value) + # 3) fix substitutions (e.g. %s/%@) + value = androidify_substitutions(value) + # 4) replace beginning and end spaces with \0020. Otherwise Tizen strips them. + value.gsub!(/\A *| *\z/) { |spaces| '\u0020' * spaces.length } + + comment = row.comment + if comment + comment = comment.gsub('--', '—') + end + + if comment && comment.length > 0 + f.puts "\t\n" + end + f.puts "\t#{value}" + end + end + end + end + + f.puts '' + end + end + end + end +end