Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add I18n syntax error translation #241

Merged
merged 13 commits into from
Aug 30, 2013
Merged

Add I18n syntax error translation #241

merged 13 commits into from
Aug 30, 2013

Conversation

sirupsen
Copy link
Contributor

Simple possible implementation of I18n support for Liquid errors, as requested in #18.

@fw42 please take a look.

require File.join(File.dirname(__FILE__), '..', 'lib', 'liquid')

$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
require 'liquid.rb'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't handle running single test files nicely otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, didn't have problems with that before. What do you mean exactly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

liquid (i18n-error) Σ ruby -Itest test/liquid/i18n_test.rb
/opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- liquid/version (LoadError)
        from /opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /Users/sirup/Dropbox/Code/liquid/lib/liquid.rb:48:in `<top (required)>'
        from /opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /Users/sirup/Dropbox/Code/liquid/test/test_helper.rb:13:in `<top (required)>'
        from /opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /opt/boxen/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from test/liquid/i18n_test.rb:1:in `<main>'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you run ruby -Itest -Ilib test/liquid/i18n_test.rb? I rarely see that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 i had the same problem before. I would, however, have this change in a isolate commit.

@fw42
Copy link
Contributor

fw42 commented Aug 15, 2013

Hm, haven't taken a very close look, but considering we only have like 5 error messages at most, this seems very overkill. Also, I don't want to call it "I18n", that's a bit confusing.

@fw42
Copy link
Contributor

fw42 commented Aug 15, 2013

@phoet, thoughts?

@@ -0,0 +1,46 @@
require 'yaml'
require 'delegate'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous attempt, I forgot to remove it.

@fw42
Copy link
Contributor

fw42 commented Aug 15, 2013

Hm, ok, on second thought, maybe it's not overkill. Seems nice actually. @arthurnn, @dylanahsmith, any comments so far?

@@ -41,7 +41,9 @@ def register_filter(mod)
end

# creates a new <tt>Template</tt> object from liquid source code
def parse(source)
def parse(source, options = {:locale => "lib/liquid/locales/en.yml"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not the right place to define default options. There is two ways to parse a template: Template.parse(...) and Template.new.parse(...). You only catch one of them. Also, your I18n.global thing doesn't seem to be thread-safe (two threads using different languages). Instead of using global variables, why not store this stuff in the Liquid context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's not thread-safe. It hit me when I went to bed I could store the I18n object in the Liquid context registers to access it anywhere, but haven't actually implemented it yet. I think this is what makes it not overkill, that you can have these objects around. It's a pretty simple class, too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, will this relative path work once this thing is packaged as a gem (and the application itself doesn't provide a locale file)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like in the test you wanna make it absolute.

@sirupsen
Copy link
Contributor Author

Since I18n is self-referential, it can stack overflow if the error message doesn't exist in the database. There are three solutions:

  1. We don't care to translate errors in I18n.
  2. Add some logic that handles this case and presents a better error than a stack overflow.
  3. We don't really care about this case as people should generally be able to copy the english locale and go from there and never have to worry about this.


private
def interpolate(name, vars)
name.gsub(/:(\w+)/) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this might match too much. Maybe we should add the possibility to escape :? Like /[^\]:(\w+)/ maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit: Good point!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for the case that someone wants to include colons in their error messages. Dunno. Not a big deal.

@sirupsen
Copy link
Contributor Author

@fw42 What should be done? Thoughts on whether the logic in Template#initialize should be moved?

@fw42
Copy link
Contributor

fw42 commented Aug 16, 2013

Wait for one of the three people I asked for comments to actually say something :P

@fw42
Copy link
Contributor

fw42 commented Aug 19, 2013

Guys, can one of you please take a look? @arthurnn, @dylanahsmith, @phoet, @trishume

@@ -101,7 +102,7 @@ def render(*args)
when nil
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
else
raise ArgumentError, "Expect Hash or Liquid::Context as parameter"
raise ArgumentError, registers[:locale].translate("errors.template.argument_hash_or_context")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not using the .t method in here? 🐹

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this message would be expected to ever how up in rendered liquid output, so do we really need to translate this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we only need to translate syntax errors? I don't know Liquid well in terms of what could be useful to translate besides that. But yes, agreed. 👍 Shouldn't use this everywhere, just where it's needed to not clutter the locale file too much.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a handful of errors other than SyntaxError. Try grep raise -R lib in the repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but which of those do we actually need to translate? Should they all be translated?

@fw42
Copy link
Contributor

fw42 commented Aug 19, 2013

I'm still not sure about calling this I18n. It's confusing.

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the :Context in this get treated as an interpolation?

Maybe a different interpolation character should be chosen, colons are common in plain english and code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be clearer if we use /%{\w+}/ syntax for interpolation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true. There is support for escaping, but it feels really awkward here. I support your idea @dylanahsmith, @fw42 any strong feelings about :symbol?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, no strong feelings

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like '%' as the escape character as well, for consistency with C printf. Or maybe for the recursive lulz the strings could be interpreted using Liquid.

@trishume
Copy link
Contributor

Looks pretty good. I agree about not naming it I18n though, maybe 'Internationalization'?

@arthurnn
Copy link
Contributor

I like the I18n name , as long as we always use it under the Liquid:: namespace .

private
def interpolate(name, vars)
name.gsub(/([^\\]):(\w+)/) {
raise TranslationError, translate("errors.i18n.undefined_interpolation", :key => $1, :name => name) unless vars[$2.to_sym]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of raising, maybe just don't interpolate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you ever want to put the interpolation syntax if the key is not passed? Shouldn't this act as much like Ruby as possible?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm yeah I guess you are right

@sirupsen
Copy link
Contributor Author

What's do you guys not like about I18n @trishume @fw42 as long as it is namespaced properly everywhere? The reason why people call things I18n and not Internationalization is because that word is so absurdly long.

@fw42
Copy link
Contributor

fw42 commented Aug 20, 2013

I was under the impression that most people associate the term "I18n" with one specific implementation of Internationalization (the one that comes with Rails). I didn't know it's just a shorter synonym. Feel free to use it then.

@arthurnn
Copy link
Contributor

It is indeed just a short term, on my old times of java development, we used to use I18n for classes and all that. http://struts.apache.org/release/1.3.x/apidocs/org/apache/struts/tiles/xmlDefinition/I18nFactorySet.html

@phoet
Copy link
Contributor

phoet commented Aug 20, 2013

@fw42 sorry, i am quite bussy right now and on vacation from thursday on. will have no time to review!

@sirupsen
Copy link
Contributor Author

@arthurnn @trishume @fw42 I removed the option passing to parse and changed the interpolation syntax.

@arthurnn
Copy link
Contributor

Really like the lib/liquid/template.rb now.. 💚 ❤️ 🍍 ❤️ 💚 .

Probably before merge we would want to squash those back and forth in one commit, but besides that I like it.
👍 on my side.

@sirupsen
Copy link
Contributor Author

Also need to actually add the translations. :-) Still don't know whether every exception should be translated, or just syntax errors. See thread above.

@trishume
Copy link
Contributor

This looks great, I like the interpolation syntax. In terms of translations I think it should be every error that can be produced by problems with a template, which means any error that a user rather than a developer will see.

That means syntax errors as well as some other errors like 'missing filter'.

@sirupsen
Copy link
Contributor Author

I'll wait with this until the new parser is merged in.

@fw42
Copy link
Contributor

fw42 commented Aug 29, 2013

@sirupsen, @trishume, lets try to get both this and the new parser shipped by tomorrow.

@trishume
Copy link
Contributor

@fw42 Agreed! Now that this PR encompasses both the new parser and fancy errors we can just merge this one and close the other.

@fw42
Copy link
Contributor

fw42 commented Aug 30, 2013

I would rather have two separate merges (first the parser branch, then this one). ⛵ 💨

@sirupsen
Copy link
Contributor Author

@fw42 agreed, that's cleaner

end

def tokenize
@output = []

loop do
while !@ss.eos?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this? Why is this PR changing lexer code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's weird.. :s Bad rebase? @trishume any ideas? You changed this recently?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that too, I have no idea why. If you look at lexer.rb in master right now it has the changes that this PR is supposedly adding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just a GitHub UI fuckup? Can you check manually before merging?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do the merge on your computer instead of in the Github UI I guess...

@fw42
Copy link
Contributor

fw42 commented Aug 30, 2013

Couple of small comments, other than that, 👍

sirupsen added a commit that referenced this pull request Aug 30, 2013
Add I18n syntax error translation
@sirupsen sirupsen merged commit 136b676 into master Aug 30, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants