From f37a984fd700029072335b8b3b375d76a430f5ca Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Wed, 14 Aug 2013 23:28:40 -0400 Subject: [PATCH 01/13] Add sketch of I18n error translation --- lib/liquid.rb | 1 + lib/liquid/i18n.rb | 46 +++++++++++++++++++++++++++++++++++++ lib/liquid/locales/en.yml | 9 ++++++++ lib/liquid/template.rb | 2 +- test/fixtures/en_locale.yml | 9 ++++++++ test/liquid/i18n_test.rb | 33 ++++++++++++++++++++++++++ test/test_helper.rb | 4 +++- 7 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 lib/liquid/i18n.rb create mode 100644 lib/liquid/locales/en.yml create mode 100644 test/fixtures/en_locale.yml create mode 100644 test/liquid/i18n_test.rb diff --git a/lib/liquid.rb b/lib/liquid.rb index 62b1c80d..22a6ddef 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -48,6 +48,7 @@ end require "liquid/version" require 'liquid/lexer' require 'liquid/parser' +require 'liquid/i18n' require 'liquid/drop' require 'liquid/extensions' require 'liquid/errors' diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb new file mode 100644 index 00000000..16e89b08 --- /dev/null +++ b/lib/liquid/i18n.rb @@ -0,0 +1,46 @@ +require 'yaml' +require 'delegate' + +module Liquid + class I18n + class TranslationError < StandardError + end + + def initialize(path) + @path = path + end + + def translate(name, vars = {}) + interpolate(deep_fetch_translation(name), vars) + end + alias_method :t, :translate + + class << self + def translate(name, vars = {}) + @@global.translate(name, vars) + end + alias_method :t, :translate + + def global=(translator) + @@global = translator + end + end + + private + def interpolate(name, vars) + name.gsub(/:(\w+)/) do + vars[$1.to_sym] or raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) + end + end + + def deep_fetch_translation(name) + name.split('.').reduce(locale) do |level, cur| + level[cur] or raise TranslationError, translate("errors.i18n.unknown_translation", :name => name) + end + end + + def locale + @locale ||= YAML.load_file(@path) + end + end +end diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml new file mode 100644 index 00000000..0ec28e12 --- /dev/null +++ b/lib/liquid/locales/en.yml @@ -0,0 +1,9 @@ +--- + errors: + i18n: + unknown_translation: "Translation for :name does not exist in locale" + undefined_interpolation: "Undefined key :key for interpolation in translation :name" + template: + argument_hash_or_context: "Expect Hash or Liquid::Context as parameter" + syntax_error: + tag_termination: "Tag ':token' was not properly terminated with regexp: :inspection" diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 87f1491c..aaf7ca2c 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -119,7 +119,7 @@ module Liquid when nil Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits) else - raise ArgumentError, "Expect Hash or Liquid::Context as parameter" + raise ArgumentError, I18n.translate("errors.template.argument_hash_or_context") end case args.last diff --git a/test/fixtures/en_locale.yml b/test/fixtures/en_locale.yml new file mode 100644 index 00000000..ee7983f8 --- /dev/null +++ b/test/fixtures/en_locale.yml @@ -0,0 +1,9 @@ +--- + simple: "less is more" + whatever: "something :something" + errors: + i18n: + undefined_interpolation: "undefined key :key" + unknown_translation: "translation ':name' wasn't found" + syntax: + oops: "something wasn't right" diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb new file mode 100644 index 00000000..93d3159c --- /dev/null +++ b/test/liquid/i18n_test.rb @@ -0,0 +1,33 @@ +require 'test_helper' + +class I18nTest < Test::Unit::TestCase + include Liquid + + def setup + @i18n = I18n.new("./test/fixtures/en_locale.yml") + end + + def test_simple_translate_string + assert_equal "less is more", @i18n.translate("simple") + end + + def test_nested_translate_string + assert_equal "something wasn't right", @i18n.translate("errors.syntax.oops") + end + + def test_single_string_interpolation + assert_equal "something different", @i18n.translate("whatever", :something => "different") + end + + def test_raises_keyerror_on_undefined_interpolation_key + assert_raise I18n::TranslationError do + @i18n.translate("whatever", :oopstypos => "yes") + end + end + + def test_raises_unknown_translation + assert_raise I18n::TranslationError do + @i18n.translate("doesnt_exist") + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index aaabf15e..cf49d474 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -7,7 +7,9 @@ begin rescue LoadError puts "Couldn't load ruby-debug. gem install ruby-debug if you need it." end -require File.join(File.dirname(__FILE__), '..', 'lib', 'liquid') + +$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')) +require 'liquid.rb' mode = :strict if env_mode = ENV['LIQUID_PARSER_MODE'] From 0dac6fe88a0c361854fa059502dea2f63f0c3384 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 15 Aug 2013 10:00:00 -0400 Subject: [PATCH 02/13] Change to absolute path in localization test --- test/liquid/i18n_test.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index 93d3159c..7afe4cbc 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -3,8 +3,12 @@ require 'test_helper' class I18nTest < Test::Unit::TestCase include Liquid + def en_locale_path + File.join(File.expand_path(File.dirname(__FILE__)), "..", "fixtures", "en_locale.yml") + end + def setup - @i18n = I18n.new("./test/fixtures/en_locale.yml") + @i18n = I18n.new en_locale_path end def test_simple_translate_string From e7bcf04d1df1deff5b0d2b44f16e89fe4b3f6ded Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 15 Aug 2013 10:01:06 -0400 Subject: [PATCH 03/13] Remove delegate require from localization --- lib/liquid/i18n.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 16e89b08..39e623e9 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -1,5 +1,4 @@ require 'yaml' -require 'delegate' module Liquid class I18n From 0a2f21386d932249f82d540694bb3cbec4bef503 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 15 Aug 2013 10:06:08 -0400 Subject: [PATCH 04/13] Add fixture helper --- test/liquid/i18n_test.rb | 6 +----- test/test_helper.rb | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index 7afe4cbc..afdda27f 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -3,12 +3,8 @@ require 'test_helper' class I18nTest < Test::Unit::TestCase include Liquid - def en_locale_path - File.join(File.expand_path(File.dirname(__FILE__)), "..", "fixtures", "en_locale.yml") - end - def setup - @i18n = I18n.new en_locale_path + @i18n = I18n.new fixture("en_locale.yml") end def test_simple_translate_string diff --git a/test/test_helper.rb b/test/test_helper.rb index cf49d474..aa2f6e75 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -21,6 +21,12 @@ Liquid::Template.error_mode = mode module Test module Unit + class TestCase + def fixture(name) + File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", name) + end + end + module Assertions include Liquid From 40fba9ee6ccb397f9af7d7fca0d4b4cf33ddf0c4 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 15 Aug 2013 10:22:29 -0400 Subject: [PATCH 05/13] Add locale to context registers --- lib/liquid/i18n.rb | 21 +++++++-------------- lib/liquid/template.rb | 5 +++-- test/liquid/i18n_test.rb | 4 ++++ test/liquid/template_test.rb | 16 +++++++++++++++- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 39e623e9..7e0687c3 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -2,10 +2,14 @@ require 'yaml' module Liquid class I18n + DEFAULT_LOCALE = File.join(File.expand_path(File.dirname(__FILE__)), "locales", "en.yml") + class TranslationError < StandardError end + + attr_reader :path - def initialize(path) + def initialize(path = DEFAULT_LOCALE) @path = path end @@ -14,15 +18,8 @@ module Liquid end alias_method :t, :translate - class << self - def translate(name, vars = {}) - @@global.translate(name, vars) - end - alias_method :t, :translate - - def global=(translator) - @@global = translator - end + def locale + @locale ||= YAML.load_file(@path) end private @@ -37,9 +34,5 @@ module Liquid level[cur] or raise TranslationError, translate("errors.i18n.unknown_translation", :name => name) end end - - def locale - @locale ||= YAML.load_file(@path) - end end end diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index aaf7ca2c..1a6dc01f 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -61,7 +61,8 @@ module Liquid end # creates a new Template from an array of tokens. Use Template.parse instead - def initialize + def initialize(options = {}) + registers[:locale] = I18n.new(options[:locale]) || I18n.new @resource_limits = {} end @@ -119,7 +120,7 @@ module Liquid when nil Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits) else - raise ArgumentError, I18n.translate("errors.template.argument_hash_or_context") + raise ArgumentError, registers[:locale].translate("errors.template.argument_hash_or_context") end case args.last diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index afdda27f..e6e0d7ad 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -30,4 +30,8 @@ class I18nTest < Test::Unit::TestCase @i18n.translate("doesnt_exist") end end + + def test_sets_default_path_to_en + assert_equal I18n::DEFAULT_LOCALE, I18n.new.path + end end diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 04f1e508..40ee971d 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -143,4 +143,18 @@ class TemplateTest < Test::Unit::TestCase assert_equal 'bar', t.parse('{{bar}}').render(drop) assert_equal 'haha', t.parse("{{baz}}").render(drop) end -end # TemplateTest + + def test_sets_default_localization_in_context + t = Template.new(:locale => fixture("en_locale.yml")) + + assert_instance_of I18n, t.registers[:locale] + assert_equal fixture("en_locale.yml"), t.registers[:locale].path + end + + def test_sets_default_localization_in_context_with_quick_initialization + t = Template.parse('{{foo}}', :locale => fixture("en_locale.yml")) + + assert_instance_of I18n, t.registers[:locale] + assert_equal fixture("en_locale.yml"), t.registers[:locale].path + end +end From 0343f6dc9438573d988d8987895907457365dc2a Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 15 Aug 2013 11:12:45 -0400 Subject: [PATCH 06/13] Add escaping of symbols --- lib/liquid/i18n.rb | 7 ++++--- test/liquid/i18n_test.rb | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 7e0687c3..44641e43 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -24,9 +24,10 @@ module Liquid private def interpolate(name, vars) - name.gsub(/:(\w+)/) do - vars[$1.to_sym] or raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) - end + name.gsub(/([^\\]):(\w+)/) { + raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) unless vars[$2.to_sym] + "#{$1}#{vars[$2.to_sym]}" + }.gsub("\\:", ":") end def deep_fetch_translation(name) diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index e6e0d7ad..76e7fdfa 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -34,4 +34,12 @@ class I18nTest < Test::Unit::TestCase def test_sets_default_path_to_en assert_equal I18n::DEFAULT_LOCALE, I18n.new.path end + + def test_escaping_of_symbols + assert_equal "do replaced! not :gsub", @i18n.send(:interpolate, + 'do :replace not \\:gsub', + { + :replace => "replaced!" + }) + end end From 5ee4f960e8a7a7a0fad6eedfedab3ffa22c29b11 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Wed, 21 Aug 2013 13:12:12 -0400 Subject: [PATCH 07/13] Move localization option to register --- lib/liquid/template.rb | 5 ++--- test/liquid/template_test.rb | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 1a6dc01f..3e627653 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -61,8 +61,7 @@ module Liquid end # creates a new Template from an array of tokens. Use Template.parse instead - def initialize(options = {}) - registers[:locale] = I18n.new(options[:locale]) || I18n.new + def initialize @resource_limits = {} end @@ -80,7 +79,7 @@ module Liquid end def registers - @registers ||= {} + @registers ||= {:locale => Liquid::I18n.new} end def assigns diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 40ee971d..8f3a6fc6 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -145,14 +145,14 @@ class TemplateTest < Test::Unit::TestCase end def test_sets_default_localization_in_context - t = Template.new(:locale => fixture("en_locale.yml")) - + t = Template.new assert_instance_of I18n, t.registers[:locale] - assert_equal fixture("en_locale.yml"), t.registers[:locale].path end def test_sets_default_localization_in_context_with_quick_initialization - t = Template.parse('{{foo}}', :locale => fixture("en_locale.yml")) + t = Template.new + t.registers[:locale] = I18n.new(fixture("en_locale.yml")) + t.parse('{{foo}}') assert_instance_of I18n, t.registers[:locale] assert_equal fixture("en_locale.yml"), t.registers[:locale].path From df5980f23f79ee48bddd569c57721c7be6339bec Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Wed, 21 Aug 2013 13:18:08 -0400 Subject: [PATCH 08/13] Change interpolation syntax to %{key} --- lib/liquid/i18n.rb | 8 ++++---- test/fixtures/en_locale.yml | 6 +++--- test/liquid/i18n_test.rb | 8 -------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 44641e43..0404c010 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -24,10 +24,10 @@ module Liquid private def interpolate(name, vars) - name.gsub(/([^\\]):(\w+)/) { - raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) unless vars[$2.to_sym] - "#{$1}#{vars[$2.to_sym]}" - }.gsub("\\:", ":") + name.gsub(/%{(\w+)}/) { + raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) unless vars[$1.to_sym] + "#{vars[$1.to_sym]}" + } end def deep_fetch_translation(name) diff --git a/test/fixtures/en_locale.yml b/test/fixtures/en_locale.yml index ee7983f8..0b113c67 100644 --- a/test/fixtures/en_locale.yml +++ b/test/fixtures/en_locale.yml @@ -1,9 +1,9 @@ --- simple: "less is more" - whatever: "something :something" + whatever: "something %{something}" errors: i18n: - undefined_interpolation: "undefined key :key" - unknown_translation: "translation ':name' wasn't found" + undefined_interpolation: "undefined key %{key}" + unknown_translation: "translation '%{name}' wasn't found" syntax: oops: "something wasn't right" diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index 76e7fdfa..e6e0d7ad 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -34,12 +34,4 @@ class I18nTest < Test::Unit::TestCase def test_sets_default_path_to_en assert_equal I18n::DEFAULT_LOCALE, I18n.new.path end - - def test_escaping_of_symbols - assert_equal "do replaced! not :gsub", @i18n.send(:interpolate, - 'do :replace not \\:gsub', - { - :replace => "replaced!" - }) - end end From 29cdabc30ef9071a4d61e2a365319408d8638ed0 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 29 Aug 2013 17:45:16 -0400 Subject: [PATCH 09/13] Move I18n to options --- lib/liquid/template.rb | 8 ++++++-- test/liquid/template_test.rb | 11 +++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 3e627653..a596bf8b 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -14,6 +14,10 @@ module Liquid # template.render('user_name' => 'bob') # class Template + DEFAULT_OPTIONS = { + :locale => I18n.new + } + attr_accessor :root, :resource_limits @@file_system = BlankFileSystem.new @@ -68,7 +72,7 @@ module Liquid # Parse source code. # Returns self for easy chaining def parse(source, options = {}) - @root = Document.new(tokenize(source), options) + @root = Document.new(tokenize(source), DEFAULT_OPTIONS.merge(options)) @warnings = nil self end @@ -79,7 +83,7 @@ module Liquid end def registers - @registers ||= {:locale => Liquid::I18n.new} + @registers ||= {} end def assigns diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 8f3a6fc6..939d4e88 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -144,17 +144,16 @@ class TemplateTest < Test::Unit::TestCase assert_equal 'haha', t.parse("{{baz}}").render(drop) end - def test_sets_default_localization_in_context + def test_sets_default_localization_in_document t = Template.new - assert_instance_of I18n, t.registers[:locale] + assert_instance_of I18n, t.root.options[:locale] end def test_sets_default_localization_in_context_with_quick_initialization t = Template.new - t.registers[:locale] = I18n.new(fixture("en_locale.yml")) - t.parse('{{foo}}') + t.parse('{{foo}}', locale: I18n.new(fixture("en_locale.yml"))) - assert_instance_of I18n, t.registers[:locale] - assert_equal fixture("en_locale.yml"), t.registers[:locale].path + assert_instance_of I18n, t.root.options[:locale] + assert_equal fixture("en_locale.yml"), t.root.options[:locale].path end end From 072c12dc47ebd65975d48331e6d9d20fdf7795d8 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 29 Aug 2013 19:11:07 -0400 Subject: [PATCH 10/13] Localize errors in Liquid --- lib/liquid/block.rb | 15 +++++++++------ lib/liquid/htmltags.rb | 2 +- lib/liquid/locales/en.yml | 21 +++++++++++++++++++-- lib/liquid/tags/assign.rb | 2 +- lib/liquid/tags/capture.rb | 2 +- lib/liquid/tags/case.rb | 6 +++--- lib/liquid/tags/cycle.rb | 2 +- lib/liquid/tags/for.rb | 6 +++--- lib/liquid/tags/if.rb | 5 ++--- lib/liquid/tags/include.rb | 2 +- test/liquid/assign_test.rb | 6 ++++++ test/liquid/template_test.rb | 1 + test/test_helper.rb | 7 +++++++ 13 files changed, 55 insertions(+), 22 deletions(-) diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index a5c3b1e4..ed7f7ace 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -41,7 +41,7 @@ module Liquid unknown_tag($1, $2, tokens) end else - raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} " + raise SyntaxError.new(options[:locale].t("errors.syntax.tag_termination", :token => token, :tag_end => TagEnd.inspect)) end when IsVariable new_var = create_variable(token) @@ -80,11 +80,14 @@ module Liquid def unknown_tag(tag, params, tokens) case tag when 'else' - raise SyntaxError, "#{block_name} tag does not expect else tag" + raise SyntaxError.new(options[:locale].t("errors.syntax.unexpected_else", + :block_name => block_name)) when 'end' - raise SyntaxError, "'end' is not a valid delimiter for #{block_name} tags. use #{block_delimiter}" + raise SyntaxError.new(options[:locale].t("errors.syntax.invalid_delimiter", + :block_name => block_name, + :block_delimiter => block_delimiter)) else - raise SyntaxError, "Unknown tag '#{tag}'" + raise SyntaxError.new(options[:locale].t("errors.syntax.unknown_tag", :tag => tag)) end end @@ -100,7 +103,7 @@ module Liquid token.scan(ContentOfVariable) do |content| return Variable.new(content.first, @options) end - raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ") + raise SyntaxError.new(options[:locale].t("errors.syntax.tag_termination", :token => token, :tag_end => TagEnd.inspect)) end def render(context) @@ -110,7 +113,7 @@ module Liquid protected def assert_missing_delimitation! - raise SyntaxError.new("#{block_name} tag was never closed") + raise SyntaxError.new(options[:locale].t("errors.syntax.tag_never_closed", :block_name => block_name)) end def render_all(list, context) diff --git a/lib/liquid/htmltags.rb b/lib/liquid/htmltags.rb index 62a53895..05b04190 100644 --- a/lib/liquid/htmltags.rb +++ b/lib/liquid/htmltags.rb @@ -11,7 +11,7 @@ module Liquid @attributes[key] = value end else - raise SyntaxError.new("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3") + raise SyntaxError.new(options[:locale].t("errors.syntax.table_row")) end super diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index 0ec28e12..f2c54195 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -5,5 +5,22 @@ undefined_interpolation: "Undefined key :key for interpolation in translation :name" template: argument_hash_or_context: "Expect Hash or Liquid::Context as parameter" - syntax_error: - tag_termination: "Tag ':token' was not properly terminated with regexp: :inspection" + syntax: + assign: "Syntax Error in 'assign' - Valid syntax: assign [var] = [source]" + capture: "Syntax Error in 'capture' - Valid syntax: capture [var]" + case: "Syntax Error in 'case' - Valid syntax: case [condition]" + case_invalid_when: "Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %}" + case_invalid_else: "Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) " + cycle: "Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]" + for: "Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]" + for_invalid_in: "For loops require an 'in' clause" + for_invalid_attribute: "Invalid attribute in for loop. Valid attributes are limit and offset" + if: "Syntax Error in tag 'if' - Valid syntax: if [expression]" + include: "Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]" + unknown_tag: "Unknown tag '%{tag}'" + invalid_delimiter: "'end' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}" + unexpected_else: "%{block_name} tag does not expect else tag" + tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}" + tag_never_closed: "'%{block_name}' tag was never closed" + meta_syntax_error: "Liquid syntax error: #{e.message}" + table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3" diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 34fdf196..45c6bed6 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -16,7 +16,7 @@ module Liquid @to = $1 @from = Variable.new($2) else - raise SyntaxError.new("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]") + raise SyntaxError.new options[:locale].t("errors.syntax.assign") end super diff --git a/lib/liquid/tags/capture.rb b/lib/liquid/tags/capture.rb index 4f5b34c9..92b99508 100644 --- a/lib/liquid/tags/capture.rb +++ b/lib/liquid/tags/capture.rb @@ -18,7 +18,7 @@ module Liquid if markup =~ Syntax @to = $1 else - raise SyntaxError.new("Syntax Error in 'capture' - Valid syntax: capture [var]") + raise SyntaxError.new(options[:locale].t("errors.syntax.capture")) end super diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index a9b2316b..ce2ad886 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -9,7 +9,7 @@ module Liquid if markup =~ Syntax @left = $1 else - raise SyntaxError.new("Syntax Error in tag 'case' - Valid syntax: case [condition]") + raise SyntaxError.new(options[:locale].t("errors.syntax.case")) end super @@ -50,7 +50,7 @@ module Liquid while markup # Create a new nodelist and assign it to the new block if not markup =~ WhenSyntax - raise SyntaxError.new("Syntax Error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ") + raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_when")) end markup = $2 @@ -63,7 +63,7 @@ module Liquid def record_else_condition(markup) if not markup.strip.empty? - raise SyntaxError.new("Syntax Error in tag 'case' - Valid else condition: {% else %} (no parameters) ") + raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_else")) end block = ElseCondition.new diff --git a/lib/liquid/tags/cycle.rb b/lib/liquid/tags/cycle.rb index e970dfbe..de811422 100644 --- a/lib/liquid/tags/cycle.rb +++ b/lib/liquid/tags/cycle.rb @@ -24,7 +24,7 @@ module Liquid @variables = variables_from_string(markup) @name = "'#{@variables.to_s}'" else - raise SyntaxError.new("Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]") + raise SyntaxError.new(options[:locale].t("errors.syntax.cycle")) end super end diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index 69fc9d33..5902704c 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -128,14 +128,14 @@ module Liquid @attributes[key] = value end else - raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]") + raise SyntaxError.new(options[:locale].t("errors.syntax.for")) end end def strict_parse(markup) p = Parser.new(markup) @variable_name = p.consume(:id) - raise SyntaxError, "For loops require an 'in' clause" unless p.id?('in') + raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_in")) unless p.id?('in') @collection_name = p.expression @name = "#{@variable_name}-#{@collection_name}" @reversed = p.id?('reversed') @@ -143,7 +143,7 @@ module Liquid @attributes = {} while p.look(:id) && p.look(:colon, 1) unless attribute = p.id?('limit') || p.id?('offset') - raise SyntaxError, "Invalid attribute in for loop. Valid attributes are limit and offset" + raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_attribute")) end p.consume val = p.expression diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index ac1767d3..c376f6c3 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -10,7 +10,6 @@ module Liquid # There are {% if count < 5 %} less {% else %} more {% endif %} items than you need. # class If < Block - SyntaxHelp = "Syntax Error in tag 'if' - Valid syntax: if [expression]" Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o @@ -54,14 +53,14 @@ module Liquid def lax_parse(markup) expressions = markup.scan(ExpressionsAndOperators).reverse - raise(SyntaxError, SyntaxHelp) unless expressions.shift =~ Syntax + raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless expressions.shift =~ Syntax condition = Condition.new($1, $2, $3) while not expressions.empty? operator = (expressions.shift).to_s.strip - raise(SyntaxError, SyntaxHelp) unless expressions.shift.to_s =~ Syntax + raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless expressions.shift.to_s =~ Syntax new_condition = Condition.new($1, $2, $3) new_condition.send(operator.to_sym, condition) diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb index 42eff176..76448f82 100644 --- a/lib/liquid/tags/include.rb +++ b/lib/liquid/tags/include.rb @@ -29,7 +29,7 @@ module Liquid end else - raise SyntaxError.new("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]") + raise SyntaxError.new(options[:locale].t("errors.syntax.include")) end super diff --git a/test/liquid/assign_test.rb b/test/liquid/assign_test.rb index d1eb6151..f4edb9aa 100644 --- a/test/liquid/assign_test.rb +++ b/test/liquid/assign_test.rb @@ -18,4 +18,10 @@ class AssignTest < Test::Unit::TestCase '{% assign foo = values | split: "," %}.{{ foo[1] }}.', 'values' => "foo,bar,baz") end + + def test_assign_syntax_error + assert_match_syntax_error(/assign/, + '{% assign foo not values %}.', + 'values' => "foo,bar,baz") + end end # AssignTest diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 939d4e88..72a12649 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -146,6 +146,7 @@ class TemplateTest < Test::Unit::TestCase def test_sets_default_localization_in_document t = Template.new + t.parse('') assert_instance_of I18n, t.root.options[:locale] end diff --git a/test/test_helper.rb b/test/test_helper.rb index aa2f6e75..e1f12f0a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -40,6 +40,13 @@ module Test assert_match expected, Template.parse(template).render(assigns) end + def assert_match_syntax_error(match, template, registers = {}) + exception = assert_raise(Liquid::SyntaxError) { + Template.parse(template).render(assigns) + } + assert_match match, exception.message + end + def with_error_mode(mode) old_mode = Liquid::Template.error_mode Liquid::Template.error_mode = mode From fc8c45ebe6722a31b583ea1ca8dd09f91979ce13 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Thu, 29 Aug 2013 21:48:01 -0400 Subject: [PATCH 11/13] Fix use of 1.9 hash syntax --- test/liquid/template_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 72a12649..5fd4d1e7 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -152,7 +152,7 @@ class TemplateTest < Test::Unit::TestCase def test_sets_default_localization_in_context_with_quick_initialization t = Template.new - t.parse('{{foo}}', locale: I18n.new(fixture("en_locale.yml"))) + t.parse('{{foo}}', :locale => I18n.new(fixture("en_locale.yml"))) assert_instance_of I18n, t.root.options[:locale] assert_equal fixture("en_locale.yml"), t.root.options[:locale].path From 380828f80756da2eb14ae571c3f53469d6c6443b Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Fri, 30 Aug 2013 12:26:23 -0400 Subject: [PATCH 12/13] Rename outdated test --- test/liquid/i18n_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index e6e0d7ad..23f6fdcb 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -19,7 +19,7 @@ class I18nTest < Test::Unit::TestCase assert_equal "something different", @i18n.translate("whatever", :something => "different") end - def test_raises_keyerror_on_undefined_interpolation_key + def test_raises_translation_error_on_undefined_interpolation_key assert_raise I18n::TranslationError do @i18n.translate("whatever", :oopstypos => "yes") end From ad184fbfc9f77680a978900c331ad1f739011f6c Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Fri, 30 Aug 2013 12:31:17 -0400 Subject: [PATCH 13/13] Remove superplus translations --- lib/liquid/i18n.rb | 4 ++-- lib/liquid/locales/en.yml | 5 ----- lib/liquid/template.rb | 2 +- test/liquid/i18n_test.rb | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index 0404c010..3ae54452 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -25,14 +25,14 @@ module Liquid private def interpolate(name, vars) name.gsub(/%{(\w+)}/) { - raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) unless vars[$1.to_sym] + raise TranslationError, "Undefined key #{$1} for interpolation in translation #{name}" unless vars[$1.to_sym] "#{vars[$1.to_sym]}" } end def deep_fetch_translation(name) name.split('.').reduce(locale) do |level, cur| - level[cur] or raise TranslationError, translate("errors.i18n.unknown_translation", :name => name) + level[cur] or raise TranslationError, "Translation for #{name} does not exist in locale #{path}" end end end diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index f2c54195..a6ce9355 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -1,10 +1,5 @@ --- errors: - i18n: - unknown_translation: "Translation for :name does not exist in locale" - undefined_interpolation: "Undefined key :key for interpolation in translation :name" - template: - argument_hash_or_context: "Expect Hash or Liquid::Context as parameter" syntax: assign: "Syntax Error in 'assign' - Valid syntax: assign [var] = [source]" capture: "Syntax Error in 'capture' - Valid syntax: capture [var]" diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index a596bf8b..1f2bfd14 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -123,7 +123,7 @@ module Liquid when nil Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits) else - raise ArgumentError, registers[:locale].translate("errors.template.argument_hash_or_context") + raise ArgumentError, "Expected Hash or Liquid::Context as parameter" end case args.last diff --git a/test/liquid/i18n_test.rb b/test/liquid/i18n_test.rb index 23f6fdcb..1042ac00 100644 --- a/test/liquid/i18n_test.rb +++ b/test/liquid/i18n_test.rb @@ -4,7 +4,7 @@ class I18nTest < Test::Unit::TestCase include Liquid def setup - @i18n = I18n.new fixture("en_locale.yml") + @i18n = I18n.new(fixture("en_locale.yml")) end def test_simple_translate_string