From 280914bdc53cc607bf64633e608c4979776af843 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Tue, 22 Nov 2016 22:26:24 +0100 Subject: [PATCH 1/3] Fixed #169 by adding proper placeholder handling to Flash formatter. --- README.md | 4 +++- lib/twine/formatters/flash.rb | 22 +++++++++++----------- lib/twine/placeholders.rb | 29 ++++++++++++++++++++++++----- test/test_formatters.rb | 9 +++++++++ test/test_placeholders.rb | 28 ++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 773e4c0..3477b1a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Twine supports [`printf` style placeholders][printf] with one peculiarity: `@` i Tags are used by Twine as a way to only work with a subset of your definitions at any given point in time. Each definition can be assigned zero or more tags which are separated by commas. Tags are optional, though highly recommended. You can get a list of all definitions currently missing tags by executing the [`validate-twine-file`](#validate-twine-file) command with the `--pedantic` option. -When generating a localization file, you can specify which definitions should be included using the `--tags` option. Provide a comma separated list of tags to match all definitions that contain any of the tags (`--tags tag1,tag2` matches all definitions tagged with `tag1` _or_ `tag2`). Provide multiple `--tags` options to match defintions containing all specified tags (`--tags tag1 --tags tag2` matches all definitions tagged with `tag1` _and_ `tag2`). You can match definitions _not_ containing a tag by prefixing the tag with a tilde (`--tags ~tag1` matches all definitions _not_ tagged with `tag1`.). All three options are combinable. +When generating a localization file, you can specify which definitions should be included using the `--tags` option. Provide a comma separated list of tags to match all definitions that contain any of the tags (`--tags tag1,tag2` matches all definitions tagged with `tag1` _or_ `tag2`). Provide multiple `--tags` options to match defintions containing all specified tags (`--tags tag1 --tags tag2` matches all definitions tagged with `tag1` _and_ `tag2`). You can match definitions _not_ containing a tag by prefixing the tag with a tilde (`--tags ~tag1` matches all definitions _not_ tagged with `tag1`). All three options are combinable. ### Whitespace @@ -93,6 +93,7 @@ Twine currently supports the following output formats: * [jquery-localize Language Files][jquerylocalize] (format: jquery) * [Django PO Files][djangopo] (format: django) * [Tizen String Resources][tizen] (format: tizen) +* [Flash/Flex Properties][flash] (format: flash) If you would like to enable Twine to create localization files in another format, read the wiki page on how to create an appropriate formatter. @@ -227,4 +228,5 @@ Many thanks to all of the contributors to the Twine project, including: [jquerylocalize]: https://github.com/coderifous/jquery-localize [djangopo]: https://docs.djangoproject.com/en/dev/topics/i18n/translation/ [tizen]: https://developer.tizen.org/documentation/articles/localization +[flash]: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html#getString() [printf]: https://en.wikipedia.org/wiki/Printf_format_string diff --git a/lib/twine/formatters/flash.rb b/lib/twine/formatters/flash.rb index 3aaee70..5a1855b 100644 --- a/lib/twine/formatters/flash.rb +++ b/lib/twine/formatters/flash.rb @@ -1,6 +1,8 @@ module Twine module Formatters class Flash < Abstract + include Twine::Placeholders + def format_name 'flash' end @@ -21,6 +23,11 @@ module Twine return end + def set_translation_for_key(key, lang, value) + value = convert_placeholders_from_flash_to_twine(value) + super(key, lang, value) + end + def read(io, lang) last_comment = nil while line = io.gets @@ -28,19 +35,13 @@ module Twine if match key = match[1] value = match[2].strip - value.gsub!(/\{[0-9]\}/, '%@') + set_translation_for_key(key, lang, value) - if last_comment - set_comment_for_key(key, last_comment) - end + set_comment_for_key(key, last_comment) if last_comment end match = /# *(.*)/.match(line) - if match - last_comment = match[1] - else - last_comment = nil - end + last_comment = match ? match[1] : nil end end @@ -65,8 +66,7 @@ module Twine end def format_value(value) - placeHolderNumber = -1 - value.gsub(/%[d@]/) { placeHolderNumber += 1; '{%d}' % placeHolderNumber } + convert_placeholders_from_twine_to_flash(value) end end end diff --git a/lib/twine/placeholders.rb b/lib/twine/placeholders.rb index fc88ae8..9f1828e 100644 --- a/lib/twine/placeholders.rb +++ b/lib/twine/placeholders.rb @@ -5,17 +5,21 @@ module Twine # Note: the ` ` (single space) flag is NOT supported PLACEHOLDER_FLAGS_WIDTH_PRECISION_LENGTH = '([-+0#])?(\d+|\*)?(\.(\d+|\*))?(hh?|ll?|L|z|j|t)?' PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH = '(\d+\$)?' + PLACEHOLDER_FLAGS_WIDTH_PRECISION_LENGTH + PLACEHOLDER_TYPES = '[diufFeEgGxXoscpaA]' + + def convert_twine_string_placeholder(input) + # %@ -> %s + input.gsub(/(%#{PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH})@/, '\1s') + end # http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling # http://stackoverflow.com/questions/4414389/android-xml-percent-symbol # https://github.com/mobiata/twine/pull/106 def convert_placeholders_from_twine_to_android(input) - placeholder_types = '[diufFeEgGxXoscpaA]' - # %@ -> %s - value = input.gsub(/(%#{PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH})@/, '\1s') + value = convert_twine_string_placeholder(input) - placeholder_syntax = PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH + placeholder_types + placeholder_syntax = PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH + PLACEHOLDER_TYPES placeholder_regex = /%#{placeholder_syntax}/ number_of_placeholders = value.scan(placeholder_regex).size @@ -30,7 +34,7 @@ module Twine return value if number_of_placeholders < 2 # number placeholders - non_numbered_placeholder_regex = /%(#{PLACEHOLDER_FLAGS_WIDTH_PRECISION_LENGTH}#{placeholder_types})/ + non_numbered_placeholder_regex = /%(#{PLACEHOLDER_FLAGS_WIDTH_PRECISION_LENGTH}#{PLACEHOLDER_TYPES})/ number_of_non_numbered_placeholders = value.scan(non_numbered_placeholder_regex).size @@ -51,5 +55,20 @@ module Twine # %s -> %@ input.gsub(placeholder_regex, '\1@') end + + # http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html#getString() + # http://soenkerohde.com/2008/07/flex-localization/comment-page-1/ + def convert_placeholders_from_twine_to_flash(input) + value = convert_twine_string_placeholder(input) + + placeholder_regex = /%#{PLACEHOLDER_PARAMETER_FLAGS_WIDTH_PRECISION_LENGTH}#{PLACEHOLDER_TYPES}/ + value.gsub(placeholder_regex).each_with_index do |match, index| + "{#{index}}" + end + end + + def convert_placeholders_from_flash_to_twine(input) + input.gsub /\{\d+\}/, '%@' + end end end diff --git a/test/test_formatters.rb b/test/test_formatters.rb index b25662a..38fb0d2 100644 --- a/test/test_formatters.rb +++ b/test/test_formatters.rb @@ -338,9 +338,18 @@ class TestFlashFormatter < FormatterTest assert_file_contents_read_correctly end + def test_set_translation_converts_placeholders + @formatter.set_translation_for_key 'key1', 'en', "value {#{rand(10)}}" + assert_equal 'value %@', @empty_twine_file.definitions_by_key['key1'].translations['en'] + end + def test_format_file formatter = Twine::Formatters::Flash.new formatter.twine_file = @twine_file assert_equal content('formatter_flash.properties'), formatter.format_file('en') end + + def test_format_value_converts_placeholders + assert_equal "value {0}", @formatter.format_value('value %d') + end end diff --git a/test/test_placeholders.rb b/test/test_placeholders.rb index 55d0f02..e67625e 100644 --- a/test/test_placeholders.rb +++ b/test/test_placeholders.rb @@ -86,4 +86,32 @@ class PlaceholderTest < TwineTest assert_equal "some %@ value", from_android("some %s value") end end + + class ToFlash < PlaceholderTest + def to_flash(value) + Twine::Placeholders.convert_placeholders_from_twine_to_flash(value) + end + + def test_replaces_placeholder + assert_equal "some {0} text", to_flash("some #{placeholder} text") + end + + def test_replaces_string_placeholder + assert_equal "some {0} text", to_flash("some #{placeholder('@')} text") + end + + def test_numbers_placeholders + assert_equal "some {0} more {1} text {2}", to_flash("some #{placeholder('@')} more #{placeholder('@')} text #{placeholder('@')}") + end + end + + class FromFlash < PlaceholderTest + def from_flash(value) + Twine::Placeholders.convert_placeholders_from_flash_to_twine(value) + end + + def test_maps_all_placeholders_to_string + assert_equal "some %@ more %@ text %@", from_flash("some {0} more {1} text {2}") + end + end end From f9720a67d7a6cbfd3b1ff05be3e1035923a6b661 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Tue, 22 Nov 2016 22:27:02 +0100 Subject: [PATCH 2/3] Implemented determine_language_given_path for Flash formatter. --- lib/twine/formatters/flash.rb | 3 ++- test/test_formatters.rb | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/twine/formatters/flash.rb b/lib/twine/formatters/flash.rb index 5a1855b..629c4d0 100644 --- a/lib/twine/formatters/flash.rb +++ b/lib/twine/formatters/flash.rb @@ -20,7 +20,8 @@ module Twine end def determine_language_given_path(path) - return + # match two-letter language code, optionally followed by a two letter region code + path.split(File::SEPARATOR).reverse.find { |segment| segment =~ /^([a-z]{2}(-[a-z]{2})?)$/i } end def set_translation_for_key(key, lang, value) diff --git a/test/test_formatters.rb b/test/test_formatters.rb index 38fb0d2..df85ab7 100644 --- a/test/test_formatters.rb +++ b/test/test_formatters.rb @@ -352,4 +352,13 @@ class TestFlashFormatter < FormatterTest def test_format_value_converts_placeholders assert_equal "value {0}", @formatter.format_value('value %d') end + + def test_deducts_language_from_resource_folder + language = %w(en de fr).sample + assert_equal language, @formatter.determine_language_given_path("locale/#{language}") + end + + def test_deducts_language_and_region_from_resource_folder + assert_equal 'de-AT', @formatter.determine_language_given_path("locale/de-AT") + end end From ecefba05119633320cd95a2e9bc7ab54fd6d9bb6 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Tue, 22 Nov 2016 22:33:41 +0100 Subject: [PATCH 3/3] Fixed #153 by removing command deprecation warning. --- lib/twine/cli.rb | 13 ------------- twine.gemspec | 2 -- 2 files changed, 15 deletions(-) diff --git a/lib/twine/cli.rb b/lib/twine/cli.rb index 783fbfd..1132078 100644 --- a/lib/twine/cli.rb +++ b/lib/twine/cli.rb @@ -139,19 +139,6 @@ module Twine exit false end - # TODO: Remove this mapping of deprecated commands some time in the future - added on 31.03. - deprecated_command_mappings = { - 'generate-string-file' => 'generate-localization-file', - 'generate-all-string-file' => 'generate-all-localization-files', - 'consume-string-file' => 'consume-localization-file', - 'consume-all-string-files' => 'consume-all-localization-files' - } - mapped_command = deprecated_command_mappings[args[0]] - if mapped_command - Twine::stderr.puts "WARNING: Twine commands names have changed. `#{args[0]}` is now `#{mapped_command}`. The old command is deprecated will soon stop working. For more information please check the documentation at https://github.com/mobiata/twine" - args[0] = mapped_command - end - number_of_needed_arguments = NEEDED_COMMAND_ARGUMENTS[args[0]] unless number_of_needed_arguments raise Twine::Error.new "Invalid command: #{args[0]}" diff --git a/twine.gemspec b/twine.gemspec index 98bc26a..d16d04b 100644 --- a/twine.gemspec +++ b/twine.gemspec @@ -31,6 +31,4 @@ Gem::Specification.new do |s| It is geared toward Mac OS X, iOS, and Android developers. desc - - s.post_install_message = "Twine command names have changed! Please check the documentation for their new names." end