twine 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +56 -69
  3. data/lib/twine.rb +11 -3
  4. data/lib/twine/cli.rb +375 -155
  5. data/lib/twine/formatters.rb +0 -5
  6. data/lib/twine/formatters/abstract.rb +43 -43
  7. data/lib/twine/formatters/android.rb +58 -59
  8. data/lib/twine/formatters/apple.rb +3 -3
  9. data/lib/twine/formatters/django.rb +15 -21
  10. data/lib/twine/formatters/flash.rb +17 -20
  11. data/lib/twine/formatters/gettext.rb +11 -15
  12. data/lib/twine/formatters/jquery.rb +8 -11
  13. data/lib/twine/formatters/tizen.rb +4 -4
  14. data/lib/twine/output_processor.rb +15 -15
  15. data/lib/twine/placeholders.rb +26 -6
  16. data/lib/twine/runner.rb +95 -95
  17. data/lib/twine/{stringsfile.rb → twine_file.rb} +53 -48
  18. data/lib/twine/version.rb +1 -1
  19. data/test/{command_test_case.rb → command_test.rb} +5 -5
  20. data/test/fixtures/{consume_loc_drop.zip → consume_localization_archive.zip} +0 -0
  21. data/test/fixtures/formatter_django.po +3 -1
  22. data/test/test_abstract_formatter.rb +40 -40
  23. data/test/test_cli.rb +313 -211
  24. data/test/test_consume_localization_archive.rb +27 -0
  25. data/test/{test_consume_string_file.rb → test_consume_localization_file.rb} +19 -19
  26. data/test/test_formatters.rb +108 -43
  27. data/test/{test_generate_all_string_files.rb → test_generate_all_localization_files.rb} +18 -18
  28. data/test/{test_generate_loc_drop.rb → test_generate_localization_archive.rb} +14 -14
  29. data/test/{test_generate_string_file.rb → test_generate_localization_file.rb} +18 -18
  30. data/test/test_output_processor.rb +26 -26
  31. data/test/test_placeholders.rb +44 -9
  32. data/test/test_twine_definition.rb +111 -0
  33. data/test/test_twine_file.rb +58 -0
  34. data/test/test_validate_twine_file.rb +61 -0
  35. data/test/twine_file_dsl.rb +12 -12
  36. data/test/{twine_test_case.rb → twine_test.rb} +1 -1
  37. metadata +23 -23
  38. data/test/test_consume_loc_drop.rb +0 -27
  39. data/test/test_strings_file.rb +0 -58
  40. data/test/test_strings_row.rb +0 -47
  41. data/test/test_validate_strings_file.rb +0 -61
@@ -1,6 +1,6 @@
1
- require 'command_test_case'
1
+ require 'command_test'
2
2
 
3
- class TestGenerateAllStringFiles < CommandTestCase
3
+ class TestGenerateAllLocalizationFiles < CommandTest
4
4
  def new_runner(create_folders, twine_file = nil)
5
5
  options = {}
6
6
  options[:output_path] = @output_dir
@@ -10,7 +10,7 @@ class TestGenerateAllStringFiles < CommandTestCase
10
10
  unless twine_file
11
11
  twine_file = build_twine_file 'en', 'es' do
12
12
  add_section 'Section' do
13
- add_row key: 'value'
13
+ add_definition key: 'value'
14
14
  end
15
15
  end
16
16
  end
@@ -18,57 +18,57 @@ class TestGenerateAllStringFiles < CommandTestCase
18
18
  Twine::Runner.new(options, twine_file)
19
19
  end
20
20
 
21
- class TestDoNotCreateFolders < TestGenerateAllStringFiles
21
+ class TestDoNotCreateFolders < TestGenerateAllLocalizationFiles
22
22
  def new_runner(twine_file = nil)
23
23
  super(false, twine_file)
24
24
  end
25
25
 
26
26
  def test_fails_if_output_folder_does_not_exist
27
27
  assert_raises Twine::Error do
28
- new_runner.generate_all_string_files
28
+ new_runner.generate_all_localization_files
29
29
  end
30
30
  end
31
31
 
32
32
  def test_does_not_create_language_folders
33
33
  Dir.mkdir File.join @output_dir, 'en.lproj'
34
- new_runner.generate_all_string_files
34
+ new_runner.generate_all_localization_files
35
35
  refute File.exists?(File.join(@output_dir, 'es.lproj')), "language folder should not be created"
36
36
  end
37
37
 
38
38
  def test_prints_empty_file_warnings
39
39
  Dir.mkdir File.join @output_dir, 'en.lproj'
40
40
  empty_twine_file = build_twine_file('en') {}
41
- new_runner(empty_twine_file).generate_all_string_files
41
+ new_runner(empty_twine_file).generate_all_localization_files
42
42
  assert_match "Skipping file at path", Twine::stderr.string
43
43
  end
44
44
  end
45
45
 
46
- class TestCreateFolders < TestGenerateAllStringFiles
46
+ class TestCreateFolders < TestGenerateAllLocalizationFiles
47
47
  def new_runner(twine_file = nil)
48
48
  super(true, twine_file)
49
49
  end
50
50
 
51
51
  def test_creates_output_folder
52
52
  FileUtils.remove_entry_secure @output_dir
53
- new_runner.generate_all_string_files
53
+ new_runner.generate_all_localization_files
54
54
  assert File.exists? @output_dir
55
55
  end
56
56
 
57
57
  def test_creates_language_folders
58
- new_runner.generate_all_string_files
58
+ new_runner.generate_all_localization_files
59
59
  assert File.exists?(File.join(@output_dir, 'en.lproj')), "language folder 'en.lproj' should be created"
60
60
  assert File.exists?(File.join(@output_dir, 'es.lproj')), "language folder 'es.lproj' should be created"
61
61
  end
62
62
 
63
63
  def test_prints_empty_file_warnings
64
64
  empty_twine_file = build_twine_file('en') {}
65
- new_runner(empty_twine_file).generate_all_string_files
65
+ new_runner(empty_twine_file).generate_all_localization_files
66
66
 
67
67
  assert_match "Skipping file at path", Twine::stderr.string
68
68
  end
69
69
  end
70
70
 
71
- class TestValidate < CommandTestCase
71
+ class TestValidate < CommandTest
72
72
  def new_runner(validate)
73
73
  Dir.mkdir File.join @output_dir, 'values-en'
74
74
 
@@ -79,23 +79,23 @@ class TestGenerateAllStringFiles < CommandTestCase
79
79
 
80
80
  twine_file = build_twine_file 'en' do
81
81
  add_section 'Section' do
82
- add_row key: 'value'
83
- add_row key: 'value'
82
+ add_definition key: 'value'
83
+ add_definition key: 'value'
84
84
  end
85
85
  end
86
86
 
87
87
  Twine::Runner.new(options, twine_file)
88
88
  end
89
89
 
90
- def test_does_not_validate_strings_file
90
+ def test_does_not_validate_twine_file
91
91
  prepare_mock_formatter Twine::Formatters::Android
92
92
 
93
- new_runner(false).generate_all_string_files
93
+ new_runner(false).generate_all_localization_files
94
94
  end
95
95
 
96
- def test_validates_strings_file_if_validate
96
+ def test_validates_twine_file_if_validate
97
97
  assert_raises Twine::Error do
98
- new_runner(true).generate_all_string_files
98
+ new_runner(true).generate_all_localization_files
99
99
  end
100
100
  end
101
101
  end
@@ -1,6 +1,6 @@
1
- require 'command_test_case'
1
+ require 'command_test'
2
2
 
3
- class TestGenerateLocDrop < CommandTestCase
3
+ class TestGenerateLocalizationArchive < CommandTest
4
4
  def new_runner(twine_file = nil)
5
5
  options = {}
6
6
  options[:output_path] = @output_path
@@ -9,7 +9,7 @@ class TestGenerateLocDrop < CommandTestCase
9
9
  unless twine_file
10
10
  twine_file = build_twine_file 'en', 'fr' do
11
11
  add_section 'Section' do
12
- add_row key: 'value'
12
+ add_definition key: 'value'
13
13
  end
14
14
  end
15
15
  end
@@ -18,13 +18,13 @@ class TestGenerateLocDrop < CommandTestCase
18
18
  end
19
19
 
20
20
  def test_generates_zip_file
21
- new_runner.generate_loc_drop
21
+ new_runner.generate_localization_archive
22
22
 
23
23
  assert File.exists?(@output_path), "zip file should exist"
24
24
  end
25
25
 
26
26
  def test_zip_file_structure
27
- new_runner.generate_loc_drop
27
+ new_runner.generate_localization_archive
28
28
 
29
29
  names = []
30
30
  Zip::File.open(@output_path) do |zipfile|
@@ -39,16 +39,16 @@ class TestGenerateLocDrop < CommandTestCase
39
39
  formatter = prepare_mock_formatter Twine::Formatters::Apple
40
40
  formatter.expects(:format_file).twice
41
41
 
42
- new_runner.generate_loc_drop
42
+ new_runner.generate_localization_archive
43
43
  end
44
44
 
45
45
  def test_prints_empty_file_warnings
46
46
  empty_twine_file = build_twine_file('en') {}
47
- new_runner(empty_twine_file).generate_loc_drop
47
+ new_runner(empty_twine_file).generate_localization_archive
48
48
  assert_match "Skipping file", Twine::stderr.string
49
49
  end
50
50
 
51
- class TestValidate < CommandTestCase
51
+ class TestValidate < CommandTest
52
52
  def new_runner(validate)
53
53
  options = {}
54
54
  options[:output_path] = @output_path
@@ -57,23 +57,23 @@ class TestGenerateLocDrop < CommandTestCase
57
57
 
58
58
  twine_file = build_twine_file 'en' do
59
59
  add_section 'Section' do
60
- add_row key: 'value'
61
- add_row key: 'value'
60
+ add_definition key: 'value'
61
+ add_definition key: 'value'
62
62
  end
63
63
  end
64
64
 
65
65
  Twine::Runner.new(options, twine_file)
66
66
  end
67
67
 
68
- def test_does_not_validate_strings_file
68
+ def test_does_not_validate_twine_file
69
69
  prepare_mock_formatter Twine::Formatters::Android
70
70
 
71
- new_runner(false).generate_loc_drop
71
+ new_runner(false).generate_localization_archive
72
72
  end
73
73
 
74
- def test_validates_strings_file_if_validate
74
+ def test_validates_twine_file_if_validate
75
75
  assert_raises Twine::Error do
76
- new_runner(true).generate_loc_drop
76
+ new_runner(true).generate_localization_archive
77
77
  end
78
78
  end
79
79
  end
@@ -1,15 +1,15 @@
1
- require 'command_test_case'
1
+ require 'command_test'
2
2
 
3
- class TestGenerateStringFile < CommandTestCase
3
+ class TestGenerateLocalizationFile < CommandTest
4
4
  def new_runner(language, file)
5
5
  options = {}
6
6
  options[:output_path] = File.join(@output_dir, file) if file
7
7
  options[:languages] = language if language
8
8
 
9
- strings = Twine::StringsFile.new
10
- strings.language_codes.concat KNOWN_LANGUAGES
9
+ twine_file = Twine::TwineFile.new
10
+ twine_file.language_codes.concat KNOWN_LANGUAGES
11
11
 
12
- Twine::Runner.new(options, strings)
12
+ Twine::Runner.new(options, twine_file)
13
13
  end
14
14
 
15
15
  def prepare_mock_format_file_formatter(formatter_class)
@@ -20,25 +20,25 @@ class TestGenerateStringFile < CommandTestCase
20
20
  def test_deducts_android_format_from_output_path
21
21
  prepare_mock_format_file_formatter Twine::Formatters::Android
22
22
 
23
- new_runner('fr', 'fr.xml').generate_string_file
23
+ new_runner('fr', 'fr.xml').generate_localization_file
24
24
  end
25
25
 
26
26
  def test_deducts_apple_format_from_output_path
27
27
  prepare_mock_format_file_formatter Twine::Formatters::Apple
28
28
 
29
- new_runner('fr', 'fr.strings').generate_string_file
29
+ new_runner('fr', 'fr.strings').generate_localization_file
30
30
  end
31
31
 
32
32
  def test_deducts_jquery_format_from_output_path
33
33
  prepare_mock_format_file_formatter Twine::Formatters::JQuery
34
34
 
35
- new_runner('fr', 'fr.json').generate_string_file
35
+ new_runner('fr', 'fr.json').generate_localization_file
36
36
  end
37
37
 
38
38
  def test_deducts_gettext_format_from_output_path
39
39
  prepare_mock_format_file_formatter Twine::Formatters::Gettext
40
40
 
41
- new_runner('fr', 'fr.po').generate_string_file
41
+ new_runner('fr', 'fr.po').generate_localization_file
42
42
  end
43
43
 
44
44
  def test_deducts_language_from_output_path
@@ -46,7 +46,7 @@ class TestGenerateStringFile < CommandTestCase
46
46
  formatter = prepare_mock_formatter Twine::Formatters::Android
47
47
  formatter.expects(:format_file).with(random_language).returns(true)
48
48
 
49
- new_runner(nil, "#{random_language}.xml").generate_string_file
49
+ new_runner(nil, "#{random_language}.xml").generate_localization_file
50
50
  end
51
51
 
52
52
  def test_returns_error_if_nothing_written
@@ -54,11 +54,11 @@ class TestGenerateStringFile < CommandTestCase
54
54
  formatter.expects(:format_file).returns(false)
55
55
 
56
56
  assert_raises Twine::Error do
57
- new_runner('fr', 'fr.xml').generate_string_file
57
+ new_runner('fr', 'fr.xml').generate_localization_file
58
58
  end
59
59
  end
60
60
 
61
- class TestValidate < CommandTestCase
61
+ class TestValidate < CommandTest
62
62
  def new_runner(validate)
63
63
  options = {}
64
64
  options[:output_path] = @output_path
@@ -68,23 +68,23 @@ class TestGenerateStringFile < CommandTestCase
68
68
 
69
69
  twine_file = build_twine_file 'en' do
70
70
  add_section 'Section' do
71
- add_row key: 'value'
72
- add_row key: 'value'
71
+ add_definition key: 'value'
72
+ add_definition key: 'value'
73
73
  end
74
74
  end
75
75
 
76
76
  Twine::Runner.new(options, twine_file)
77
77
  end
78
78
 
79
- def test_does_not_validate_strings_file
79
+ def test_does_not_validate_twine_file
80
80
  prepare_mock_formatter Twine::Formatters::Android
81
81
 
82
- new_runner(false).generate_string_file
82
+ new_runner(false).generate_localization_file
83
83
  end
84
84
 
85
- def test_validates_strings_file_if_validate
85
+ def test_validates_twine_file_if_validate
86
86
  assert_raises Twine::Error do
87
- new_runner(true).generate_string_file
87
+ new_runner(true).generate_localization_file
88
88
  end
89
89
  end
90
90
  end
@@ -1,84 +1,84 @@
1
- require 'twine_test_case'
1
+ require 'twine_test'
2
2
 
3
- class TestOutputProcessor < TwineTestCase
3
+ class TestOutputProcessor < TwineTest
4
4
  def setup
5
5
  super
6
6
 
7
- @strings = build_twine_file 'en', 'fr' do
7
+ @twine_file = build_twine_file 'en', 'fr' do
8
8
  add_section 'Section' do
9
- add_row key1: 'value1', tags: ['tag1']
10
- add_row key2: 'value2', tags: ['tag1', 'tag2']
11
- add_row key3: 'value3', tags: ['tag2']
12
- add_row key4: { en: 'value4-en', fr: 'value4-fr' }
9
+ add_definition key1: 'value1', tags: ['tag1']
10
+ add_definition key2: 'value2', tags: ['tag1', 'tag2']
11
+ add_definition key3: 'value3', tags: ['tag2']
12
+ add_definition key4: { en: 'value4-en', fr: 'value4-fr' }
13
13
  end
14
14
  end
15
15
  end
16
16
 
17
17
  def test_includes_all_keys_by_default
18
- processor = Twine::Processors::OutputProcessor.new(@strings, {})
18
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, {})
19
19
  result = processor.process('en')
20
20
 
21
- assert_equal %w(key1 key2 key3 key4), result.strings_map.keys.sort
21
+ assert_equal %w(key1 key2 key3 key4), result.definitions_by_key.keys.sort
22
22
  end
23
23
 
24
24
  def test_filter_by_tag
25
- processor = Twine::Processors::OutputProcessor.new(@strings, { tags: ['tag1'] })
25
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, { tags: [['tag1']] })
26
26
  result = processor.process('en')
27
27
 
28
- assert_equal %w(key1 key2), result.strings_map.keys.sort
28
+ assert_equal %w(key1 key2), result.definitions_by_key.keys.sort
29
29
  end
30
30
 
31
31
  def test_filter_by_multiple_tags
32
- processor = Twine::Processors::OutputProcessor.new(@strings, { tags: ['tag1', 'tag2'] })
32
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, { tags: [['tag1', 'tag2']] })
33
33
  result = processor.process('en')
34
34
 
35
- assert_equal %w(key1 key2 key3), result.strings_map.keys.sort
35
+ assert_equal %w(key1 key2 key3), result.definitions_by_key.keys.sort
36
36
  end
37
37
 
38
38
  def test_filter_untagged
39
- processor = Twine::Processors::OutputProcessor.new(@strings, { tags: ['tag1'], untagged: true })
39
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, { tags: [['tag1']], untagged: true })
40
40
  result = processor.process('en')
41
41
 
42
- assert_equal %w(key1 key2 key4), result.strings_map.keys.sort
42
+ assert_equal %w(key1 key2 key4), result.definitions_by_key.keys.sort
43
43
  end
44
44
 
45
45
  def test_include_translated
46
- processor = Twine::Processors::OutputProcessor.new(@strings, { include: :translated })
46
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, { include: :translated })
47
47
  result = processor.process('fr')
48
48
 
49
- assert_equal %w(key4), result.strings_map.keys.sort
49
+ assert_equal %w(key4), result.definitions_by_key.keys.sort
50
50
  end
51
51
 
52
52
  def test_include_untranslated
53
- processor = Twine::Processors::OutputProcessor.new(@strings, { include: :untranslated })
53
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, { include: :untranslated })
54
54
  result = processor.process('fr')
55
55
 
56
- assert_equal %w(key1 key2 key3), result.strings_map.keys.sort
56
+ assert_equal %w(key1 key2 key3), result.definitions_by_key.keys.sort
57
57
  end
58
58
 
59
- class TranslationFallback < TwineTestCase
59
+ class TranslationFallback < TwineTest
60
60
  def setup
61
61
  super
62
62
 
63
- @strings = build_twine_file 'en', 'fr', 'de' do
63
+ @twine_file = build_twine_file 'en', 'fr', 'de' do
64
64
  add_section 'Section' do
65
- add_row key1: { en: 'value1-en', fr: 'value1-fr' }
65
+ add_definition key1: { en: 'value1-en', fr: 'value1-fr' }
66
66
  end
67
67
  end
68
68
  end
69
69
 
70
70
  def test_fallback_to_default_language
71
- processor = Twine::Processors::OutputProcessor.new(@strings, {})
71
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, {})
72
72
  result = processor.process('de')
73
73
 
74
- assert_equal 'value1-en', result.strings_map['key1'].translations['de']
74
+ assert_equal 'value1-en', result.definitions_by_key['key1'].translations['de']
75
75
  end
76
76
 
77
77
  def test_fallback_to_developer_language
78
- processor = Twine::Processors::OutputProcessor.new(@strings, {developer_language: 'fr'})
78
+ processor = Twine::Processors::OutputProcessor.new(@twine_file, {developer_language: 'fr'})
79
79
  result = processor.process('de')
80
80
 
81
- assert_equal 'value1-fr', result.strings_map['key1'].translations['de']
81
+ assert_equal 'value1-fr', result.definitions_by_key['key1'].translations['de']
82
82
  end
83
83
  end
84
84
 
@@ -1,6 +1,6 @@
1
- require 'twine_test_case'
1
+ require 'twine_test'
2
2
 
3
- class PlaceholderTestCase < TwineTestCase
3
+ class PlaceholderTest < TwineTest
4
4
  def assert_starts_with(prefix, value)
5
5
  msg = message(nil) { "Expected #{mu_pp(value)} to start with #{mu_pp(prefix)}" }
6
6
  assert value.start_with?(prefix), msg
@@ -11,23 +11,25 @@ class PlaceholderTestCase < TwineTestCase
11
11
  lucky = lambda { rand > 0.5 }
12
12
  placeholder = '%'
13
13
  placeholder += (rand * 20).to_i.to_s + '$' if lucky.call
14
- placeholder += '-+ 0#'.chars.to_a.sample if lucky.call
14
+ placeholder += '-+0#'.chars.to_a.sample if lucky.call
15
15
  placeholder += (0.upto(20).map(&:to_s) << "*").sample if lucky.call
16
16
  placeholder += '.' + (0.upto(20).map(&:to_s) << "*").sample if lucky.call
17
17
  placeholder += %w(h hh l ll L z j t).sample if lucky.call
18
18
  placeholder += type || 'diufFeEgGxXocpaA'.chars.to_a.sample # this does not contain s or @ because strings are a special case
19
19
  end
20
- end
21
20
 
22
- class PlaceholderTest < TwineTestCase
23
- class ToAndroid < PlaceholderTestCase
21
+ class ToAndroid < PlaceholderTest
24
22
  def to_android(value)
25
23
  Twine::Placeholders.convert_placeholders_from_twine_to_android(value)
26
24
  end
27
25
 
28
- def test_replaces_string_placeholder
26
+ def test_replaces_simple_string_placeholder
27
+ assert_equal "some '%s' value", to_android("some '%@' value")
28
+ end
29
+
30
+ def test_replaces_complicated_string_placeholder
29
31
  placeholder = placeholder('@')
30
- expected = placeholder
32
+ expected = placeholder.dup
31
33
  expected[-1] = 's'
32
34
  assert_equal "some #{expected} value", to_android("some #{placeholder} value")
33
35
  end
@@ -41,6 +43,11 @@ class PlaceholderTest < TwineTestCase
41
43
  assert_equal "some % value", to_android("some % value")
42
44
  end
43
45
 
46
+ def test_does_not_modify_single_percent_signs_when_followed_by_space_and_format_letter
47
+ # Said differently: formartter parser should not recognize %a in "70% and"
48
+ assert_equal 'If 70% and 30% dog 80% end', to_android('If 70% and 30% dog 80% end')
49
+ end
50
+
44
51
  def test_escapes_single_percent_signs_if_placeholder_present
45
52
  assert_starts_with "some %% v", to_android("some % value #{placeholder}")
46
53
  end
@@ -74,7 +81,7 @@ class PlaceholderTest < TwineTestCase
74
81
  end
75
82
  end
76
83
 
77
- class FromAndroid < PlaceholderTestCase
84
+ class FromAndroid < PlaceholderTest
78
85
  def from_android(value)
79
86
  Twine::Placeholders.convert_placeholders_from_android_to_twine(value)
80
87
  end
@@ -83,4 +90,32 @@ class PlaceholderTest < TwineTestCase
83
90
  assert_equal "some %@ value", from_android("some %s value")
84
91
  end
85
92
  end
93
+
94
+ class ToFlash < PlaceholderTest
95
+ def to_flash(value)
96
+ Twine::Placeholders.convert_placeholders_from_twine_to_flash(value)
97
+ end
98
+
99
+ def test_replaces_placeholder
100
+ assert_equal "some {0} text", to_flash("some #{placeholder} text")
101
+ end
102
+
103
+ def test_replaces_string_placeholder
104
+ assert_equal "some {0} text", to_flash("some #{placeholder('@')} text")
105
+ end
106
+
107
+ def test_numbers_placeholders
108
+ assert_equal "some {0} more {1} text {2}", to_flash("some #{placeholder('@')} more #{placeholder('@')} text #{placeholder('@')}")
109
+ end
110
+ end
111
+
112
+ class FromFlash < PlaceholderTest
113
+ def from_flash(value)
114
+ Twine::Placeholders.convert_placeholders_from_flash_to_twine(value)
115
+ end
116
+
117
+ def test_maps_all_placeholders_to_string
118
+ assert_equal "some %@ more %@ text %@", from_flash("some {0} more {1} text {2}")
119
+ end
120
+ end
86
121
  end