gherkin 1.0.2-java

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 (89) hide show
  1. data/.gitignore +7 -0
  2. data/.mailmap +2 -0
  3. data/History.txt +9 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +38 -0
  6. data/Rakefile +48 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/gherkin +5 -0
  9. data/cucumber.yml +3 -0
  10. data/features/feature_parser.feature +206 -0
  11. data/features/native_lexer.feature +19 -0
  12. data/features/parser_with_native_lexer.feature +205 -0
  13. data/features/pretty_printer.feature +14 -0
  14. data/features/step_definitions/gherkin_steps.rb +34 -0
  15. data/features/step_definitions/pretty_printer_steps.rb +56 -0
  16. data/features/steps_parser.feature +46 -0
  17. data/features/support/env.rb +33 -0
  18. data/gherkin.gemspec +155 -0
  19. data/java/.gitignore +2 -0
  20. data/java/Gherkin.iml +24 -0
  21. data/java/build.xml +13 -0
  22. data/java/src/gherkin/FixJava.java +34 -0
  23. data/java/src/gherkin/Lexer.java +5 -0
  24. data/java/src/gherkin/LexingError.java +7 -0
  25. data/java/src/gherkin/Listener.java +27 -0
  26. data/java/src/gherkin/ParseError.java +22 -0
  27. data/java/src/gherkin/Parser.java +185 -0
  28. data/java/src/gherkin/lexer/.gitignore +1 -0
  29. data/java/src/gherkin/parser/StateMachineReader.java +62 -0
  30. data/lib/.gitignore +4 -0
  31. data/lib/gherkin.rb +2 -0
  32. data/lib/gherkin/c_lexer.rb +10 -0
  33. data/lib/gherkin/cli/main.rb +34 -0
  34. data/lib/gherkin/core_ext/array.rb +5 -0
  35. data/lib/gherkin/i18n.rb +87 -0
  36. data/lib/gherkin/i18n.yml +535 -0
  37. data/lib/gherkin/i18n_lexer.rb +29 -0
  38. data/lib/gherkin/java_lexer.rb +10 -0
  39. data/lib/gherkin/lexer.rb +44 -0
  40. data/lib/gherkin/parser.rb +19 -0
  41. data/lib/gherkin/parser/meta.txt +4 -0
  42. data/lib/gherkin/parser/root.txt +9 -0
  43. data/lib/gherkin/parser/steps.txt +3 -0
  44. data/lib/gherkin/rb_lexer.rb +10 -0
  45. data/lib/gherkin/rb_lexer/.gitignore +1 -0
  46. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  47. data/lib/gherkin/rb_parser.rb +117 -0
  48. data/lib/gherkin/tools.rb +8 -0
  49. data/lib/gherkin/tools/files.rb +30 -0
  50. data/lib/gherkin/tools/pretty_listener.rb +84 -0
  51. data/lib/gherkin/tools/reformat.rb +19 -0
  52. data/lib/gherkin/tools/stats.rb +21 -0
  53. data/lib/gherkin/tools/stats_listener.rb +50 -0
  54. data/nativegems.sh +5 -0
  55. data/ragel/i18n/.gitignore +1 -0
  56. data/ragel/lexer.c.rl.erb +403 -0
  57. data/ragel/lexer.java.rl.erb +200 -0
  58. data/ragel/lexer.rb.rl.erb +171 -0
  59. data/ragel/lexer_common.rl.erb +46 -0
  60. data/spec/gherkin/c_lexer_spec.rb +21 -0
  61. data/spec/gherkin/fixtures/1.feature +8 -0
  62. data/spec/gherkin/fixtures/complex.feature +43 -0
  63. data/spec/gherkin/fixtures/i18n_fr.feature +13 -0
  64. data/spec/gherkin/fixtures/i18n_no.feature +6 -0
  65. data/spec/gherkin/fixtures/i18n_zh-CN.feature +8 -0
  66. data/spec/gherkin/fixtures/simple.feature +3 -0
  67. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  68. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  69. data/spec/gherkin/i18n_lexer_spec.rb +22 -0
  70. data/spec/gherkin/i18n_spec.rb +57 -0
  71. data/spec/gherkin/java_lexer_spec.rb +20 -0
  72. data/spec/gherkin/parser_spec.rb +28 -0
  73. data/spec/gherkin/rb_lexer_spec.rb +18 -0
  74. data/spec/gherkin/sexp_recorder.rb +29 -0
  75. data/spec/gherkin/shared/lexer_spec.rb +433 -0
  76. data/spec/gherkin/shared/py_string_spec.rb +124 -0
  77. data/spec/gherkin/shared/table_spec.rb +97 -0
  78. data/spec/gherkin/shared/tags_spec.rb +50 -0
  79. data/spec/spec_helper.rb +53 -0
  80. data/tasks/bench.rake +186 -0
  81. data/tasks/bench/feature_builder.rb +49 -0
  82. data/tasks/bench/generated/.gitignore +1 -0
  83. data/tasks/bench/null_listener.rb +4 -0
  84. data/tasks/compile.rake +70 -0
  85. data/tasks/cucumber.rake +20 -0
  86. data/tasks/ragel_task.rb +70 -0
  87. data/tasks/rdoc.rake +12 -0
  88. data/tasks/rspec.rake +15 -0
  89. metadata +196 -0
@@ -0,0 +1,22 @@
1
+ package gherkin;
2
+
3
+ import java.util.List;
4
+
5
+ public class ParseError extends RuntimeException {
6
+ private final String state;
7
+ private final List<String> expectedEvents;
8
+
9
+ public ParseError(String state, String event, List<String> expectedEvents, int line) {
10
+ super("Parse error on line " + line + ". Found " + event + " when expecting one of: " + FixJava.join(expectedEvents, ", ") + ". (Current state: " + state + ").");
11
+ this.state = state;
12
+ this.expectedEvents = expectedEvents;
13
+ }
14
+
15
+ public String state() {
16
+ return state;
17
+ }
18
+
19
+ public List<String> expectedEvents() {
20
+ return expectedEvents;
21
+ }
22
+ }
@@ -0,0 +1,185 @@
1
+ package gherkin;
2
+
3
+ import gherkin.parser.StateMachineReader;
4
+
5
+ import java.util.*;
6
+ import java.util.regex.Matcher;
7
+ import java.util.regex.Pattern;
8
+
9
+ public class Parser implements Listener {
10
+ List<Machine> machines = new ArrayList<Machine>();
11
+
12
+ private Listener listener;
13
+ private boolean throwOnError;
14
+
15
+ public Parser(Listener listener) {
16
+ this(listener, true);
17
+ }
18
+
19
+ public Parser(Listener listener, boolean throwOnError) {
20
+ this(listener, throwOnError, "root");
21
+ }
22
+
23
+ public Parser(Listener listener, boolean throwOnError, String machineName) {
24
+ this.listener = listener;
25
+ this.throwOnError = throwOnError;
26
+ pushMachine(machineName);
27
+ }
28
+
29
+ private void pushMachine(String machineName) {
30
+ machines.add(new Machine(this, machineName));
31
+ }
32
+
33
+ private void popMachine() {
34
+ machines.remove(machines.size() - 1);
35
+ }
36
+
37
+ public void tag(String name, int line) {
38
+ if (event("tag", line))
39
+ listener.tag(name, line);
40
+ }
41
+
42
+ public void py_string(String string, int line) {
43
+ if (event("py_string", line))
44
+ listener.py_string(string, line);
45
+ }
46
+
47
+ public void feature(String keyword, String name, int line) {
48
+ if (event("feature", line))
49
+ listener.feature(keyword, name, line);
50
+ }
51
+
52
+ public void background(String keyword, String name, int line) {
53
+ if (event("background", line))
54
+ listener.background(keyword, name, line);
55
+ }
56
+
57
+ public void scenario(String keyword, String name, int line) {
58
+ if (event("scenario", line))
59
+ listener.scenario(keyword, name, line);
60
+ }
61
+
62
+ public void scenario_outline(String keyword, String name, int line) {
63
+ if (event("scenario_outline", line))
64
+ listener.scenario_outline(keyword, name, line);
65
+ }
66
+
67
+ public void examples(String keyword, String name, int line) {
68
+ if (event("examples", line))
69
+ listener.examples(keyword, name, line);
70
+ }
71
+
72
+ public void step(String keyword, String name, int line) {
73
+ if (event("step", line))
74
+ listener.step(keyword, name, line);
75
+ }
76
+
77
+ public void comment(String content, int line) {
78
+ if (event("comment", line))
79
+ listener.comment(content, line);
80
+ }
81
+
82
+ public void table(List<List<String>> rows, int line) {
83
+ if (event("table", line))
84
+ listener.table(rows, line);
85
+ }
86
+
87
+ public void syntax_error(String name, String event, List<String> strings, int line) {
88
+ }
89
+
90
+ private boolean event(String event, int line) {
91
+ try {
92
+ machine().event(event, line);
93
+ return true;
94
+ } catch (ParseError e) {
95
+ if (throwOnError) {
96
+ throw e;
97
+ } else {
98
+ listener.syntax_error(e.state(), event, e.expectedEvents(), line);
99
+ return false;
100
+ }
101
+ }
102
+ }
103
+
104
+ private Machine machine() {
105
+ return machines.get(machines.size() - 1);
106
+ }
107
+
108
+ private static class Machine {
109
+ private static final Pattern PUSH = Pattern.compile("push\\((.+)\\)");
110
+ private static final Map<String, Map<String, Map<String, String>>> TRANSITION_MAPS = new HashMap<String, Map<String, Map<String, String>>>();
111
+
112
+ private final Parser parser;
113
+ private final String name;
114
+ private String state;
115
+ private Map<String, Map<String, String>> transitionMap;
116
+
117
+ public Machine(Parser parser, String name) {
118
+ this.parser = parser;
119
+ this.name = name;
120
+ this.state = name;
121
+ this.transitionMap = transitionMap(name);
122
+ }
123
+
124
+ public void event(String event, int line) {
125
+ Map<String, String> states = transitionMap.get(state);
126
+ if (states == null) {
127
+ throw new RuntimeException("Unknown state: " + state + " for machine " + name);
128
+ }
129
+ String newState = states.get(event);
130
+ if (newState == null) {
131
+ throw new RuntimeException("Unknown transition: " + event + " among " + states + " for machine " + name + " in state " + state);
132
+ }
133
+ if ("E".equals(newState)) {
134
+ throw new ParseError(state, event, expectedEvents(), line);
135
+ } else {
136
+ Matcher push = PUSH.matcher(newState);
137
+ if (push.matches()) {
138
+ parser.pushMachine(push.group(1));
139
+ parser.event(event, line);
140
+ } else if ("pop()".equals(newState)) {
141
+ parser.popMachine();
142
+ parser.event(event, line);
143
+ } else {
144
+ state = newState;
145
+ }
146
+ }
147
+ }
148
+
149
+ private List<String> expectedEvents() {
150
+ List<String> result = new ArrayList<String>();
151
+ for (String event : transitionMap.get(state).keySet()) {
152
+ if (!transitionMap.get(state).get(event).equals("E")) {
153
+ result.add(event);
154
+ }
155
+ }
156
+ Collections.sort(result);
157
+ return result;
158
+ }
159
+
160
+ private Map<String, Map<String, String>> transitionMap(String name) {
161
+ Map<String, Map<String, String>> map = TRANSITION_MAPS.get(name);
162
+ if(map == null) {
163
+ map = buildTransitionMap(name);
164
+ TRANSITION_MAPS.put(name, map);
165
+ }
166
+ return map;
167
+ }
168
+
169
+ private Map<String, Map<String, String>> buildTransitionMap(String name) {
170
+ Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
171
+ List<List<String>> transitionTable = new StateMachineReader(name).transitionTable();
172
+ List<String> events = transitionTable.get(0).subList(1, transitionTable.get(0).size());
173
+ for (List<String> actions : transitionTable.subList(1, transitionTable.size())) {
174
+ Map<String, String> transitions = new HashMap<String, String>();
175
+ int col = 1;
176
+ for (String event : events) {
177
+ transitions.put(event, actions.get(col++));
178
+ }
179
+ String state = actions.get(0);
180
+ result.put(state, transitions);
181
+ }
182
+ return result;
183
+ }
184
+ }
185
+ }
@@ -0,0 +1 @@
1
+ *.java
@@ -0,0 +1,62 @@
1
+ package gherkin.parser;
2
+
3
+ import gherkin.FixJava;
4
+ import gherkin.Lexer;
5
+ import gherkin.Listener;
6
+ import gherkin.lexer.En;
7
+
8
+ import java.io.IOException;
9
+ import java.util.List;
10
+
11
+ public class StateMachineReader implements Listener {
12
+ private final String machinePath;
13
+ private List<List<String>> transitionTable;
14
+
15
+ public StateMachineReader(String name) {
16
+ machinePath = "/gherkin/parser/" + name + ".txt";
17
+ }
18
+
19
+ public List<List<String>> transitionTable() {
20
+ Lexer lexer = new En(this);
21
+ try {
22
+ lexer.scan(FixJava.readResourceAsString(machinePath));
23
+ } catch (IOException e) {
24
+ throw new RuntimeException("Fatal error. Couldn't read " + machinePath);
25
+ }
26
+ return transitionTable;
27
+ }
28
+
29
+ public void tag(String name, int line) {
30
+ }
31
+
32
+ public void comment(String content, int line) {
33
+ }
34
+
35
+ public void feature(String keyword, String name, int line) {
36
+ }
37
+
38
+ public void background(String keyword, String name, int line) {
39
+ }
40
+
41
+ public void scenario(String keyword, String name, int line) {
42
+ }
43
+
44
+ public void scenario_outline(String keyword, String name, int line) {
45
+ }
46
+
47
+ public void examples(String keyword, String name, int line) {
48
+ }
49
+
50
+ public void step(String keyword, String name, int line) {
51
+ }
52
+
53
+ public void py_string(String string, int line) {
54
+ }
55
+
56
+ public void syntax_error(String name, String event, List<String> strings, int line) {
57
+ }
58
+
59
+ public void table(List<List<String>> rows, int line) {
60
+ transitionTable = rows;
61
+ }
62
+ }
@@ -0,0 +1,4 @@
1
+ *.bundle
2
+ *.dll
3
+ *.so
4
+ *.jar
@@ -0,0 +1,2 @@
1
+ require 'gherkin/i18n_lexer'
2
+ require 'gherkin/parser'
@@ -0,0 +1,10 @@
1
+ module Gherkin
2
+ module CLexer
3
+ def self.[](i18n_language)
4
+ name = i18n_language.gsub(/[\s-]/, '')
5
+ require "gherkin_lexer_#{name}"
6
+ i18n_lexer_class_name = name.capitalize
7
+ const_get(i18n_lexer_class_name)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'trollop'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'trollop'
6
+ end
7
+ require 'gherkin/tools'
8
+
9
+ module Gherkin
10
+ module Cli
11
+ class Main
12
+ def self.run(args)
13
+ Trollop::options(args) do
14
+ banner "Super fast gherkin parser"
15
+ stop_on Tools::SUB_COMMANDS
16
+ end
17
+
18
+ cmd_name = args.shift
19
+ begin
20
+ die("Missing command") if cmd_name.nil?
21
+ Tools.const_get(cmd_name.capitalize.to_sym).new(args).run
22
+ rescue NameError
23
+ die("Unknown command #{cmd_name}")
24
+ rescue => e
25
+ Trollop::die(e.message)
26
+ end
27
+ end
28
+
29
+ def self.die(msg)
30
+ Trollop::die("#{msg}\nusage: gherkin COMMAND [ARGS]\nAvailable commands: #{Tools::SUB_COMMANDS.join(' ')}")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def utf8_pack(fmt)
3
+ (RUBY_VERSION =~ /^1\.9/) ? pack(fmt).force_encoding("UTF-8") : pack(fmt)
4
+ end
5
+ end
@@ -0,0 +1,87 @@
1
+ require 'yaml'
2
+
3
+ module Gherkin
4
+ class I18n
5
+ KEYWORD_KEYS = %w{name native feature background scenario scenario_outline examples given when then and but}
6
+ LANGUAGES = YAML.load_file(File.dirname(__FILE__) + '/i18n.yml')
7
+
8
+ class << self
9
+ # Used by code generators for other lexer tools like pygments lexer and textmate bundle
10
+ def all
11
+ LANGUAGES.keys.sort.map{|key| get(key)}
12
+ end
13
+
14
+ def get(key)
15
+ languages[key] ||= new(key)
16
+ end
17
+
18
+ def languages
19
+ @languages ||= {}
20
+ end
21
+ end
22
+
23
+ attr_reader :key
24
+
25
+ def initialize(key)
26
+ @key = key
27
+ @keywords = LANGUAGES[key]
28
+ raise "Language not supported: #{key.inspect}" if @key.nil?
29
+ @keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
30
+ end
31
+
32
+ def sanitized_key
33
+ @key.gsub(/[\s-]/, '')
34
+ end
35
+
36
+ def incomplete?
37
+ KEYWORD_KEYS.detect{|key| @keywords[key].nil?}
38
+ end
39
+
40
+ def feature_keywords
41
+ keywords('feature')
42
+ end
43
+
44
+ def scenario_keywords
45
+ keywords('scenario')
46
+ end
47
+
48
+ def scenario_outline_keywords
49
+ keywords('scenario_outline')
50
+ end
51
+
52
+ def background_keywords
53
+ keywords('background')
54
+ end
55
+
56
+ def examples_keywords
57
+ keywords('examples')
58
+ end
59
+
60
+ def but_keywords(space=true)
61
+ keywords('but', space)
62
+ end
63
+
64
+ def and_keywords(space=true)
65
+ keywords('and', space)
66
+ end
67
+
68
+ def step_keywords
69
+ %w{given when then and but}.map{|key| keywords(key, true)}.flatten.uniq
70
+ end
71
+
72
+ def keywords(key, space=false)
73
+ raise "No #{key} in #{@keywords.inspect}" if @keywords[key].nil?
74
+ @keywords[key].split('|').map{|kw| space ? keyword_space(kw) : kw}
75
+ end
76
+
77
+ def adverbs
78
+ %w{given when then and but}.map{|keyword| @keywords[keyword].split('|').map{|w| w.gsub(/[\s<']/, '')}}.flatten
79
+ end
80
+
81
+ private
82
+
83
+ def keyword_space(val)
84
+ (val + ' ').sub(/< $/,'')
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,535 @@
1
+ # encoding: UTF-8
2
+ # We use the codes here (prefer 2 letters when possible)
3
+ # http://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
4
+ #
5
+ # If you want several aliases for a keyword, just separate them
6
+ # with a | character. Make sure there are no ambiguities in the
7
+ # keywords.
8
+ #
9
+ "en":
10
+ name: English
11
+ native: English
12
+ feature: Feature
13
+ background: Background
14
+ scenario: Scenario
15
+ scenario_outline: Scenario Outline
16
+ examples: Examples|Scenarios
17
+ given: "*|Given"
18
+ when: "*|When"
19
+ then: "*|Then"
20
+ and: "*|And"
21
+ but: "*|But"
22
+
23
+ # Please help us keeping the languages below uptodate. The parsers for a language
24
+ # that is missing a keyword will expect the English word until the missing word(s)
25
+ # are added.
26
+ #
27
+ # Please keep the grammars in alphabetical order by name from here and down.
28
+
29
+ "ar":
30
+ name: Arabic
31
+ native: العربية
32
+ feature: خاصية
33
+ background: الخلفية
34
+ scenario: سيناريو
35
+ scenario_outline: سيناريو مخطط
36
+ examples: امثلة
37
+ given: "*|بفرض"
38
+ when: "*|متى|عندما"
39
+ then: "*|اذاً|ثم"
40
+ and: "*|و"
41
+ but: "*|لكن"
42
+ "bg":
43
+ name: Bulgarian
44
+ native: български
45
+ feature: Функционалност
46
+ background: Предистория
47
+ scenario: Сценарий
48
+ scenario_outline: Рамка на сценарий
49
+ examples: Примери
50
+ given: "*|Дадено"
51
+ when: "*|Когато"
52
+ then: "*|То"
53
+ and: "*|И"
54
+ but: "*|Но"
55
+ "cat":
56
+ name: Catalan
57
+ native: català
58
+ background: Rerefons|Antecedents
59
+ feature: Característica
60
+ scenario: Escenari
61
+ scenario_outline: Esquema de l'escenari
62
+ examples: Exemples
63
+ given: "*|Donat|Donada"
64
+ when: "*|Quan"
65
+ then: "*|Aleshores"
66
+ and: "*|I"
67
+ but: "*|Però"
68
+ "cy":
69
+ name: Welsh
70
+ native: Cymraeg
71
+ background: Cefndir
72
+ feature: Arwedd
73
+ scenario: Scenario
74
+ scenario_outline: Scenario Amlinellol
75
+ examples: Enghreifftiau
76
+ given: "*|anrhegedig a"
77
+ when: "*|Pryd"
78
+ then: "*|Yna"
79
+ and: "*|A"
80
+ but: "*|Ond"
81
+ "cs":
82
+ name: Czech
83
+ native: Česky
84
+ feature: Požadavek
85
+ background: Pozadí|Kontext
86
+ scenario: Scénář
87
+ scenario_outline: Náčrt Scénáře|Osnova scénáře
88
+ examples: Příklady
89
+ given: "*|Pokud"
90
+ when: "*|Když"
91
+ then: "*|Pak"
92
+ and: "*|A|A také"
93
+ but: "*|Ale"
94
+ "da":
95
+ name: Danish
96
+ native: dansk
97
+ feature: Egenskab
98
+ background: Baggrund
99
+ scenario: Scenarie
100
+ scenario_outline: Abstrakt Scenario
101
+ examples: Eksempler
102
+ given: "*|Givet"
103
+ when: "*|Når"
104
+ then: "*|Så"
105
+ and: "*|Og"
106
+ but: "*|Men"
107
+ "de":
108
+ name: German
109
+ native: Deutsch
110
+ feature: Funktionalität
111
+ background: Grundlage
112
+ scenario: Szenario
113
+ scenario_outline: Szenariogrundriss
114
+ examples: Beispiele
115
+ given: "*|Gegeben sei"
116
+ when: "*|Wenn"
117
+ then: "*|Dann"
118
+ and: "*|Und"
119
+ but: "*|Aber"
120
+ "en-au":
121
+ name: Australian
122
+ native: Australian
123
+ feature: Crikey
124
+ background: Background
125
+ scenario: Mate
126
+ scenario_outline: Blokes
127
+ examples: Cobber
128
+ given: "*|Ya know how"
129
+ when: "*|When"
130
+ then: "*|Ya gotta"
131
+ and: "*|N"
132
+ but: "*|Cept"
133
+ "en-lol":
134
+ name: LOLCAT
135
+ native: LOLCAT
136
+ feature: OH HAI
137
+ background: B4
138
+ scenario: MISHUN
139
+ scenario_outline: MISHUN SRSLY
140
+ examples: EXAMPLZ
141
+ given: "*|I CAN HAZ"
142
+ when: "*|WEN"
143
+ then: "*|DEN"
144
+ and: "*|AN"
145
+ but: "*|BUT"
146
+ "en-tx":
147
+ name: Texan
148
+ native: Texan
149
+ feature: Feature
150
+ background: Background
151
+ scenario: Scenario
152
+ scenario_outline: All y'all
153
+ examples: Examples
154
+ given: "*|Given y'all"
155
+ when: "*|When y'all"
156
+ then: "*|Then y'all"
157
+ and: "*|And y'all"
158
+ but: "*|But y'all"
159
+ "es":
160
+ name: Spanish
161
+ native: español
162
+ background: Antecedentes
163
+ feature: Característica
164
+ scenario: Escenario
165
+ scenario_outline: Esquema del escenario
166
+ examples: Ejemplos
167
+ given: "*|Dado"
168
+ when: "*|Cuando"
169
+ then: "*|Entonces"
170
+ and: "*|Y"
171
+ but: "*|Pero"
172
+ "et":
173
+ name: Estonian
174
+ native: eesti keel
175
+ feature: Omadus
176
+ background: Taust
177
+ scenario: Stsenaarium
178
+ scenario_outline: Raamstsenaarium
179
+ examples: Juhtumid
180
+ given: "*|Eeldades"
181
+ when: "*|Kui"
182
+ then: "*|Siis"
183
+ and: "*|Ja"
184
+ but: "*|Kuid"
185
+ "fi":
186
+ name: Finnish
187
+ native: suomi
188
+ feature: Ominaisuus
189
+ background: Tausta
190
+ scenario: Tapaus
191
+ scenario_outline: Tapausaihio
192
+ examples: Tapaukset
193
+ given: "*|Oletetaan"
194
+ when: "*|Kun"
195
+ then: "*|Niin"
196
+ and: "*|Ja"
197
+ but: "*|Mutta"
198
+ "fr":
199
+ name: French
200
+ native: français
201
+ feature: Fonctionnalité
202
+ background: Contexte
203
+ scenario: Scénario
204
+ scenario_outline: Plan du scénario|Plan du Scénario
205
+ examples: Exemples
206
+ given: "*|Soit|Etant donné"
207
+ when: "*|Quand|Lorsque|Lorsqu'<"
208
+ then: "*|Alors"
209
+ and: "*|Et"
210
+ but: "*|Mais"
211
+ "he":
212
+ name: Hebrew
213
+ native: עברית
214
+ feature: תכונה
215
+ background: רקע
216
+ scenario: תרחיש
217
+ scenario_outline: תבנית תרחיש
218
+ examples: דוגמאות
219
+ given: "*|בהינתן"
220
+ when: "*|כאשר"
221
+ then: "*|אז|אזי"
222
+ and: "*|וגם"
223
+ but: "*|אבל"
224
+ "hr":
225
+ name: Croatian
226
+ native: hrvatski
227
+ feature: Osobina|Mogućnost|Mogucnost
228
+ background: Pozadina
229
+ scenario: Scenarij
230
+ scenario_outline: Skica|Koncept
231
+ examples: Primjeri|Scenariji
232
+ given: "*|Zadan|Zadani|Zadano"
233
+ when: "*|Kada|Kad"
234
+ then: "*|Onda"
235
+ and: "*|I"
236
+ but: "*|Ali"
237
+ "hu":
238
+ name: Hungarian
239
+ native: magyar
240
+ feature: Jellemző
241
+ background: Háttér
242
+ scenario: Forgatókönyv
243
+ scenario_outline: Forgatókönyv vázlat
244
+ examples: Példák
245
+ given: "*|Ha"
246
+ when: "*|Majd"
247
+ then: "*|Akkor"
248
+ and: "*|És"
249
+ but: "*|De"
250
+ "id":
251
+ name: Indonesian
252
+ native: Bahasa Indonesia
253
+ feature: Fitur
254
+ background: Dasar
255
+ scenario: Skenario
256
+ scenario_outline: Skenario konsep
257
+ examples: Contoh
258
+ given: "*|Dengan"
259
+ when: "*|Ketika"
260
+ then: "*|Maka"
261
+ and: "*|Dan"
262
+ but: "*|Tapi"
263
+ "it":
264
+ name: Italian
265
+ native: italiano
266
+ feature: Funzionalità
267
+ background: Contesto
268
+ scenario: Scenario
269
+ scenario_outline: Schema dello scenario
270
+ examples: Esempi
271
+ given: "*|Dato"
272
+ when: "*|Quando"
273
+ then: "*|Allora"
274
+ and: "*|E"
275
+ but: "*|Ma"
276
+ "ja":
277
+ name: Japanese
278
+ native: 日本語
279
+ feature: フィーチャ|機能
280
+ background: 背景
281
+ scenario: シナリオ
282
+ scenario_outline: シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ
283
+ examples: 例|サンプル
284
+ given: "*|前提<"
285
+ when: "*|もし<"
286
+ then: "*|ならば<"
287
+ and: "*|かつ<"
288
+ but: "*|しかし<|但し<|ただし<"
289
+ "ko":
290
+ name: Korean
291
+ native: 한국어
292
+ background: 배경
293
+ feature: 기능
294
+ scenario: 시나리오
295
+ scenario_outline: 시나리오 개요
296
+ examples: 예
297
+ given: "*|조건<"
298
+ when: "*|만일<"
299
+ then: "*|그러면<"
300
+ and: "*|그리고<"
301
+ but: "*|하지만<"
302
+ "lt":
303
+ name: Lithuanian
304
+ native: lietuvių kalba
305
+ feature: Savybė
306
+ background: Kontekstas
307
+ scenario: Scenarijus
308
+ scenario_outline: Scenarijaus šablonas
309
+ examples: Pavyzdžiai|Scenarijai|Variantai
310
+ given: "*|Duota"
311
+ when: "*|Kai"
312
+ then: "*|Tada"
313
+ and: "*|Ir"
314
+ but: "*|Bet"
315
+ "lv":
316
+ name: Latvian
317
+ native: latviešu
318
+ feature: Funkcionalitāte|Fīča
319
+ background: Konteksts|Situācija
320
+ scenario: Scenārijs
321
+ scenario_outline: Scenārijs pēc parauga
322
+ examples: Piemēri|Paraugs
323
+ given: "*|Kad"
324
+ when: "*|Ja"
325
+ then: "*|Tad"
326
+ and: "*|Un"
327
+ but: "*|Bet"
328
+ "nl":
329
+ name: Dutch
330
+ native: Nederlands
331
+ feature: Functionaliteit
332
+ background: Achtergrond
333
+ scenario: Scenario
334
+ scenario_outline: Abstract Scenario
335
+ examples: Voorbeelden
336
+ given: "*|Gegeven|Stel"
337
+ when: "*|Als"
338
+ then: "*|Dan"
339
+ and: "*|En"
340
+ but: "*|Maar"
341
+ "no":
342
+ name: Norwegian
343
+ native: norsk
344
+ feature: Egenskap
345
+ background: Bakgrunn
346
+ scenario: Scenario
347
+ scenario_outline: Abstrakt Scenario
348
+ examples: Eksempler
349
+ given: "*|Gitt"
350
+ when: "*|Når"
351
+ then: "*|Så"
352
+ and: "*|Og"
353
+ but: "*|Men"
354
+ "pl":
355
+ name: Polish
356
+ native: polski
357
+ feature: Właściwość
358
+ background: Założenia
359
+ scenario: Scenariusz
360
+ scenario_outline: Szablon scenariusza
361
+ examples: Przykłady
362
+ given: "*|Zakładając"
363
+ when: "*|Jeżeli"
364
+ then: "*|Wtedy"
365
+ and: "*|Oraz"
366
+ but: "*|Ale"
367
+ "pt":
368
+ name: Portuguese
369
+ native: português
370
+ background: Contexto
371
+ feature: Funcionalidade
372
+ scenario: Cenário|Cenario
373
+ scenario_outline: Esquema do Cenário|Esquema do Cenario
374
+ examples: Exemplos
375
+ given: "*|Dado"
376
+ when: "*|Quando"
377
+ then: "*|Então|Entao"
378
+ and: "*|E"
379
+ but: "*|Mas"
380
+ "ro":
381
+ name: Romanian
382
+ native: română
383
+ background: Conditii
384
+ feature: Functionalitate
385
+ scenario: Scenariu
386
+ scenario_outline: Scenariul de sablon
387
+ examples: Exemplele
388
+ given: "*|Daca"
389
+ when: "*|Cand"
390
+ then: "*|Atunci"
391
+ and: "*|Si"
392
+ but: "*|Dar"
393
+ "ro2":
394
+ name: Romanian (diacritical)
395
+ native: română (diacritical)
396
+ background: Condiţii
397
+ feature: Funcționalitate
398
+ scenario: Scenariu
399
+ scenario_outline: Scenariul de şablon
400
+ examples: Exemplele
401
+ given: "*|Dacă"
402
+ when: "*|Când"
403
+ then: "*|Atunci"
404
+ and: "*|Și"
405
+ but: "*|Dar"
406
+ "ru":
407
+ name: Russian
408
+ native: русский
409
+ feature: Функционал
410
+ background: Предыстория
411
+ scenario: Сценарий
412
+ scenario_outline: Структура сценария
413
+ examples: Значения
414
+ given: "*|Допустим"
415
+ when: "*|Если"
416
+ then: "*|То"
417
+ and: "*|И|К тому же"
418
+ but: "*|Но|А"
419
+ "se":
420
+ name: Swedish
421
+ native: Svenska
422
+ feature: Egenskap
423
+ background: Bakgrund
424
+ scenario: Scenario
425
+ scenario_outline: Abstrakt Scenario
426
+ examples: Exempel
427
+ given: "*|Givet"
428
+ when: "*|När"
429
+ then: "*|Så"
430
+ and: "*|Och"
431
+ but: "*|Men"
432
+ "sk":
433
+ name: Slovak
434
+ native: Slovensky
435
+ feature: Požiadavka
436
+ background: Pozadie
437
+ scenario: Scenár
438
+ scenario_outline: Náčrt Scenáru
439
+ examples: Príklady
440
+ given: "*|Pokiaľ"
441
+ when: "*|Keď"
442
+ then: "*|Tak"
443
+ and: "*|A"
444
+ but: "*|Ale"
445
+ "sr-Latn":
446
+ name: Serbian_latin
447
+ native: Srpski_latinica
448
+ feature: Funkcionalnost|Mogućnost|Mogucnost|Osobina
449
+ background: Kontekst|Osnova|Pozadina
450
+ scenario: Scenario|Primer
451
+ scenario_outline: Struktura scenarija|Skica|Koncept
452
+ examples: Primeri|Scenariji
453
+ given: "*|Zadato|Zadate|Zatati"
454
+ when: "*|Kada|Kad"
455
+ then: "*|Onda"
456
+ and: "*|I"
457
+ but: "*|Ali"
458
+ "sr":
459
+ name: Serbian
460
+ native: Српски
461
+ feature: Функционалност|Могућност|Особина
462
+ background: Контекст|Основа|Позадина
463
+ scenario: Сценарио|Пример
464
+ scenario_outline: Структура сценарија|Скица|Концепт
465
+ examples: Примери|Сценарији
466
+ given: "*|Задато|Задате|Задати"
467
+ when: "*|Када|Кад"
468
+ then: "*|Онда"
469
+ and: "*|И"
470
+ but: "*|Али"
471
+ "tr":
472
+ name: Turkish
473
+ native: Türkçe
474
+ feature: Özellik
475
+ background: Geçmiş
476
+ scenario: Senaryo
477
+ scenario_outline: Senaryo taslağı
478
+ examples: Örnekler
479
+ given: "*|Diyelim ki"
480
+ when: "*|Eğer ki"
481
+ then: "*|O zaman"
482
+ and: "*|Ve"
483
+ but: "*|Fakat|Ama"
484
+ "uz":
485
+ name: Uzbek
486
+ native: Узбекча
487
+ feature: Функционал
488
+ background: Тарих
489
+ scenario: Сценарий
490
+ scenario_outline: Сценарий структураси
491
+ examples: Мисоллар
492
+ given: "*|Агар"
493
+ when: "*|Агар"
494
+ then: "*|Унда"
495
+ and: "*|Ва"
496
+ but: "*|Лекин|Бирок|Аммо"
497
+ "vi":
498
+ name: Vietnamese
499
+ native: Tiếng Việt
500
+ feature: Tính năng
501
+ background: Bối cảnh
502
+ scenario: Tình huống|Kịch bản
503
+ scenario_outline: Khung tình huống|Khung kịch bản
504
+ examples: Dữ liệu
505
+ given: "*|Biết|Cho"
506
+ when: "*|Khi"
507
+ then: "*|Thì"
508
+ and: "*|Và"
509
+ but: "*|Nhưng"
510
+ "zh-CN":
511
+ name: Chinese simplified
512
+ native: 简体中文
513
+ feature: 功能
514
+ background: 背景
515
+ scenario: 场景
516
+ scenario_outline: 场景大纲
517
+ examples: 例子
518
+ given: "*|假如<"
519
+ when: "*|当<"
520
+ then: "*|那么<"
521
+ and: "*|而且<"
522
+ but: "*|但是<"
523
+ "zh-TW":
524
+ name: Chinese traditional
525
+ native: 繁體中文
526
+ feature: 功能
527
+ background: 背景
528
+ scenario: 場景|劇本
529
+ scenario_outline: 場景大綱|劇本大綱
530
+ examples: 例子
531
+ given: "*|假設<"
532
+ when: "*|當<"
533
+ then: "*|那麼<"
534
+ and: "*|而且<|並且<"
535
+ but: "*|但是<"