Coder Social home page Coder Social logo

balinterdi / i15r Goto Github PK

View Code? Open in Web Editor NEW
113.0 8.0 32.0 421 KB

Replaces plain text strings in your views and replaces them with I18n message strings so you only have to provide the translations (i15r = internationalizer)

License: MIT License

Ruby 95.11% HTML 4.89%

i15r's Introduction

I15r Build Status Code Climate

Goal

You prefer polishing your views to manually replacing strings in them to make them i18n compatible. If I got that one right, i15r is for you. It automates the process that would otherwise drive most of us nuts.

Summary

I15r (Internationalizer) searches for all the non-i18n texts in your erb and haml templates in the given file/directory and replaces them with I18n messages.

The message string is based on the path of the file in which the text was found and the text itself that was replaced.

E.g

(in file app/views/users/new.html.erb)
<label for="user-name">Name</label>
<input type="text" id="user-name" name="user[name]" />

will be replaced by:

(in file app/views/users/new.html.erb)
<label for="user-name"><%= I18n.t("users.new.name") %></label>
<input type="text" id="user-name" name="user[name]" />

and

(in file app/views/member/users/edit.html.erb)
<label for="user-name">Name</label>
<input type="text" id="user-name" name="user[name]" />

will be replaced by

(in file app/views/member/users/edit.html.erb)
<label for="user-name"><%= I18n.t("member.users.edit.name") %></label>
<input type="text" id="user-name" name="user[name]" />

Installation

Standalone

gem install i15r

In-app

Put the following in your Gemfile:

gem 'i15r', '~> 0.5.1'

Usage

Convert a single file

i15r path/leading/to/template

Convert all files in a directory (deep search)

i15r path/leading/to/directory

All files with an erb or haml suffix in that directory or somewhere in the hierarchy below will be converted.

Dry run

By default, i15r overwrites all the source files with the i18n message strings it generates. If you first want to see what would be replaced, you should do:

i15r app/views/users -n

or

i15r app/views/users --dry-run

Custom prefix

If you don't want the file path to appear in the i18n message string, you can pass a prefix parameter that will be used to generate the message strings. For example if you have the following in a file called app/views/users/new.html.erb:

<label for="user-name">Name</label>
<input type="text" id="user-name" name="user[name]" />

And then call:

i15r app/views/users/new.html.erb --prefix my_project

The file will then contain:

<label for="user-name"><%= I18n.t("my_project.name") %></label>
<input type="text" id="user-name" name="user[name]" />

If you want the a prefix plus the file path to appear in the i18n message string, you can pass a prefix_with_path parameter:

i15r app/views/users/new.html.erb --prefix_with_path my_project

The above file will then contain:

<label for="user-name"><%= I18n.t("my_project.users.new.name") %></label>
<input type="text" id="user-name" name="user[name]" />

Override I18n.t function name

If you don't want to use the full I18n.t name, use the override_i18n_method parameter:

i15r app/views/users/new.html.erb --override_i18n_method t

This will cause output that normally results in:

<label for="user-name"><%= I18n.t("users.new.name") %></label>

to result in

<label for="user-name"><%= t("users.new.name") %></label>

No default translation

If you want to skip the default translation, you must add the --no-default flag

For example, if calling

i15r app/views/users/new.html.erb

results in

<label for="user-name"><%= I18n.t("users.new.name", :default => 'Name') %></label>

Adding the --no-default flag

i15r app/views/users/new.html.erb --no-default

results in

<label for="user-name"><%= I18n.t("users.new.name") %></label>

Design principles & suggested use

I15R takes the 80-20 approach. It focuses on finding most of the text that needs to be replaced in your templates and replacing them with the correct i18n strings. It forgoes the 100% hit rate in favor of getting the 80% right and keeping the code (relatively) simple. Consequently, please report any bug that concerns strings that should not have been replaced or ones that have been replaced incorrectly.

A good practice is to first run i15r with the --dry-run option to see what would be replaced and then run it for real, without the --dry-run option. You can also run it on files that have already been "internationalized" since i15r will just skip those rows.

See also

Your next step is probably to create a YML locale file containing all the strings i15r generated. You're in luck! missing_t is a gem that can do this for you.

Contributing

Please submit any bugs or feature requests to the issue tracker.

If you'd like to contibute, please see Contributing.

License

Copyright (c) 2009 Balint Erdi

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

i15r's People

Contributors

alepore avatar balinterdi avatar giosensation avatar kassio avatar molpe avatar nberenbold avatar p avatar zyphlar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

i15r's Issues

Add missing translations automatically instead of hardcoding default into view

Awesome gem. I've found myself wanting this gem, and now I have the gem, wanting this feature.
Ideally the config/locales/en.yml would just get populated with the discovered strings instead of them getting optionally hardcoded as defaults in the views.

I had a look at the code, and realised it wouldn't be easy to do cleanly without a bit of a refactor.

I think it would suit the visitor pattern: http://blog.bigbinary.com/2013/07/07/visitor-pattern-and-double-dispatch.html

Here's a sketch of the beginnings of it:
https://gist.github.com/markburns/7182190

If this is something you think the gem can/should do, then I'd like to give a crack at a PR.

Parsing issue

Unknown why i15r had issues with this line. Maybe it's because of the custom form generator we're using that provides a :label attribute? A very interesting failure mode.

-<%= f.text_field :feature_list, :size=>60, :label=>'Feature flags', :append=>' (space separated)', :help=>"Known: #{@features.join(', ')}" %>
+<%= f.text_field :feature_list, :size=>60, :label=>I18n.t("admin.accounts.form.feature_flags_append=>space_separated_help=>known{@featuresjoin_", :default => 'Feature flags', :append=>' (space separated)', :help=>"Known: #{@features.join(', '))}" %>

-<%= f.text_field :account_id, :label=>'Account ID', :size=>12, :readonly=>true, :clear=>false %>
+<%= f.text_field :account_id, :label=>'Account ID', I18n.t("admin.guests.form.size", :default => "size")=>12, :readonly=>true, :clear=>false %>

-<%= f.text_field :cluster_name, :label=>'Location', :size=>12, :readonly=>true %>
+<%= f.text_field :cluster_name, :label=>'Location', I18n.t("admin.guests.form.size", :default => "size")=>12, :readonly=>true %>

Replace multiple texts on the same line

This one is rather big because we have to make sure that:

  • All texts that need to be international are correctly replaced by i18n message strings
  • Text inside i18n message strings are not replaced
  • When run for a line that has some text replaced, it only replaces the ones that still need to be replaced

Missing replacements

Lines like the following ones (taken from scaffolded Rails artefacts) aren't properly replaced when running 'i15r .' from a Rails app root directory:

Controller 'create' action:
format.html { redirect_to @Company, notice: 'Company was successfully created.' }

Controller 'update' action:
format.html { redirect_to @Company, notice: 'Company was successfully updated.' }

index.html.erb view:
<%= link_to I18n.t("companies.index.destroy"), company, method: :delete, data: { confirm: 'Are you sure?' } %>

Does not work with slim templater

$ i15r /path/to/app/views/shared/_my_account.html.slim -n
Running in dry-run mode
/path/to/app/views/shared/_my_account.html.slim:

/home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r/pattern_matcher.rb:36:in `const_get': uninitialized constant SlimTransformer (NameError)
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r/pattern_matcher.rb:36:in `initialize'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:84:in `new'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:84:in `sub_plain_strings'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:79:in `internationalize_file'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:99:in `block in internationalize!'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:99:in `each'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/lib/i15r.rb:99:in `internationalize!'
    from /home/adrianov/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i15r-0.5.5/bin/i15r:56:in `<top (required)>'
    from /home/adrianov/.rbenv/versions/2.2.3/bin/i15r:23:in `load'
    from /home/adrianov/.rbenv/versions/2.2.3/bin/i15r:23:in `<main>'

Automatic creation of the .yml

Hi Balint! How are you?

I'm using your gem and it works fine, congratulations!

I'd like to suggest a new feature that would save still more time: when replacements in views are generated, it could also generate a list of keys to translate.

Example:

<label for="user-name"><%= I18n.t("my_project.name") %></label>
<input type="text" id="user-name" name="user[name]" />

<label for="user-age"><%= I18n.t("my_project.age") %></label>
<input type="text" id="user-age" name="user[age]" />

would generate:

my_project:
  name: name
  age: age

Thanks for your work.

Limited usefulness

Hi,

I just ran i15r on an inherited project, and it runs mostly fine. Thanks for the good work!

However, I'm not sure of why would I want to run a tool that doesn't generate any yml file.

  • If I don't use --no-default, I get e.g. 1000 entries like I18n.t("users.new.name", :default => 'Name'), and I still will have to manually create 1000 entries in en.yml. Even if I do that, then I'd have to manually remove (default: 'foo') from each t call, for ensuring DRY/correctness.
  • If I use --no-default, any app will become empty/broken until you manually create 1000 entries in en.yml.

Either option is undesirable. As I see it, this gem would be only be useful if it generates a yml file as well.

Probably overwriting en.yml would be obstrusive/error-prone. However, generating a separate yml file could allow the developer to adapt it as he wishes.

Do you think you can make this happen?

For now I will be giving it a try, in my fork.

Cheers - Victor

Fails to work on app/foo where foo is not "views"

I have an application using https://github.com/kevgo/sections_rails. Trying to run i15r app/sections produces:

/home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/lib/i15r.rb:43:in `file_path_to_message_prefix': No app. subfolders were found to determine prefix. Path is /home/rvm/apps/foo/app/sections/foo/edit/_edit.html.haml (I15R::AppFolderNotFound)
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/lib/i15r.rb:60:in `internationalize_file'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/lib/i15r.rb:80:in `block in internationalize!'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/lib/i15r.rb:80:in `each'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/lib/i15r.rb:80:in `internationalize!'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/gems/i15r-0.5.1/bin/i15r:46:in `'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/bin/i15r:23:in `load'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/bin/i15r:23:in `'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `eval'
    from /home/rvm/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `'

There should be either a way for me to specify what the app root is, or i15r should determine that by itself, perhaps by traversing the tree up until it finds an "app" directory.

Attempts to internationalize numbers

i15r produced:

-  %span.num 12
-  Notifications
+  %span.num= I18n.t("shared.notifications_button.notifications_button.12", :default => "12")
+  = I18n.t("shared.notifications_button.notifications_button.notifications", :default => "Notifications")

Internationalization of the number 12 is not wanted.

3 specs not passing in ruby1.8

They do pass in ruby1.9 but I am not sure they really get properly replaced. Insert spec snippets in test file and see. Also, try to make it work for Ruby1.8.

Invalid byte sequence in US-ASCII

Hello,

Launching i15r (with the dry run option), I got the following error:

/Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r/pattern_matcher.rb:44:in split': invalid byte sequence in US-ASCII (ArgumentError) from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r/pattern_matcher.rb:44:inrun'
from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r.rb:84:in sub_plain_strings' from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r.rb:77:ininternationalize_file'
from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r.rb:94:in block in internationalize!' from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r.rb:94:ineach'
from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/lib/i15r.rb:94:in internationalize!' from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/gems/i15r-0.5.3/bin/i15r:53:in<top (required)>'
from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/bin/i15r:23:in load' from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/bin/i15r:23:in

'
from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/bin/ruby_executable_hooks:15:in eval' from /Users/jorisvh/.rvm/gems/ruby-2.0.0-p576/bin/ruby_executable_hooks:15:in'

The issue was that I left a comment in French in my code (with the é letter), so it was not even due to some hardcoded string to replace. It could be really great to use i15r with full UTF-8 support.

Thank you and keep up the good work !

Joris

haml tags fail

Nice gem, thanks. Unfortunatly I cannot use it on my haml views. Here is the output (partial) of a dry run:

- %p

  • = I18n.t("devise.registrations.edit.%p")

- %h2 Resend unlock instructions

  • = I18n.t("devise.unlocks.new.%h2_resend_unlock_instructions")

- %i (we need your current password to confirm your changes)

  • %i I18n.t("devise.registrations.edit.(we_need_your_current_password_to_confirm_your_changes)")
    

The %tags are removed & included in the translation. Some invalid chars are not escaped.

Cheers,
Jej

handle i15r messages in partials

Currently it generates something like this:

en:
  tickets:
    _book_info:
      book_info: BOOK INFO

Probably just removing the underscore is ok.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.