i18n_screwdriver 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,21 +1,4 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in datatrans.gemspec
3
+ # Specify your gem's dependencies in i18n_screwdriver.gemspec
4
4
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- i18n_screwdriver (0.4.0)
4
+ i18n_screwdriver (1.0.0)
5
5
  rails (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -41,6 +41,7 @@ GEM
41
41
  erubis (2.7.0)
42
42
  hike (1.2.1)
43
43
  i18n (0.6.0)
44
+ json (1.6.1)
44
45
  mail (2.3.0)
45
46
  i18n (>= 0.4.0)
46
47
  mime-types (~> 1.16)
@@ -73,7 +74,8 @@ GEM
73
74
  rdoc (~> 3.4)
74
75
  thor (~> 0.14.6)
75
76
  rake (0.9.2)
76
- rdoc (3.9.4)
77
+ rdoc (3.10)
78
+ json (~> 1.4)
77
79
  rspec (2.6.0)
78
80
  rspec-core (~> 2.6.0)
79
81
  rspec-expectations (~> 2.6.0)
data/README.rdoc CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  Translating applications is often a pain in the ass. The problem with rails i18n
4
4
  is that you have to use keys for every string to translate.
5
-
6
5
  That is one too many abstraction layers - I love the gettext syntax but I want to
7
- stick to the rails standard libraries. Therefor I created this small toolbox.
6
+ stick to the rails standard libraries. Therefor I created this small toolbox.
8
7
 
9
8
  == Installation
10
9
 
@@ -20,35 +19,44 @@ Then run the generator that copies the translation rake task to your application
20
19
 
21
20
  Set these constants to make i18n screwdriver aware of the languages you are using
22
21
 
23
- DEFAULT_LANGUAGE = 'de'
24
- FOREIGN_LANGUAGES = ['en, 'fr', 'it']
22
+ I18n.default_locale
23
+ I18n.available_locales
25
24
 
26
- In your views, helpers and controllers use the convenient underscore helper method for all your translations
25
+ In your views, helpers and controllers use the convenient underscore helper method for all your translations
27
26
 
28
27
  _("your translation")
29
28
 
30
29
  When you are done you have 2 helper rake tasks. The first one scans all your views, controllers and
31
30
  helpers for translations. It removes unused translation strings and creates an application.<lang>.yml file
32
- for each of your APPLICATION_LANGUAGES.
31
+ for each of your I18n.available_locales.
33
32
 
34
33
  rake i18n:update
35
34
 
36
- The seconds one lets you translate your application.<lang>.yml file line by line. Of course
35
+ The second one lets you translate your application.<lang>.yml file line by line. Of course
37
36
  you can edit the application.<lang>.yml file itself - but dont do that for your default language file.
38
37
  It gets recreated everytime you run the tasks - edit those translations in your views e.g. itself.
39
38
 
40
39
  TRANSLATE=en rake i18n:translate
41
40
 
41
+ == Test Helpers
42
+
43
+ In your tests (functionals and integration) you can use the same translation helper
44
+
45
+ _("your translation")
46
+
42
47
  == Next steps
43
48
 
44
- * fix drawback that multiple translations on the same line are currently not recognized, happens very well with options for select tags
45
49
  * also recognize model validation error messages
46
- * test more
50
+ * DRY the code
51
+ * test more (= test at all)
47
52
  * use ruby_parser instead of regex
48
- * support interpolation like "my name is #{user.full_name} and I am living in #{user.location}"
53
+ * support interpolation like the following (take care about naming - could be different in other languages)
54
+
55
+
56
+ _("my name is %{name} and I am living in %{location}", :name => @name, :location => @location)
49
57
 
50
58
  == Contributing to i18n_screwdriver
51
-
59
+
52
60
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
53
61
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
54
62
  * Fork the project
@@ -59,4 +67,4 @@ It gets recreated everytime you run the tasks - edit those translations in your
59
67
 
60
68
  == Copyright
61
69
 
62
- Copyright (c) 2010-2011 Tobias Miesel. Released unter the MIT license.
70
+ Copyright (c) 2010 Tobias Miesel & Corin Langosch. Released unter the MIT license.
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require 'bundler/gem_tasks'
1
+ require "bundler/gem_tasks"
@@ -1,12 +1,13 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
+ require "i18n_screwdriver/version"
3
4
 
4
5
  Gem::Specification.new do |s|
5
6
  s.name = "i18n_screwdriver"
6
- s.version = "0.6.0"
7
- s.authors = ["Tobias Miesel"]
8
- s.email = ["agileapplications@gmail.com"]
9
- s.homepage = "http://github.com/agileapplications/i18n_screwdriver"
7
+ s.version = I18nScrewdriver::VERSION
8
+ s.authors = ["Tobias Miesel", "Corin Langosch"]
9
+ s.email = ["agileapplications@gmail.com", "info@corinlangosch.com"]
10
+ s.homepage = "https://github.com/agileapplications/i18n_screwdriver"
10
11
  s.summary = %q{make translating with rails i18n fun again}
11
12
  s.description = %q{make translating with rails i18n fun again}
12
13
 
@@ -16,7 +17,9 @@ Gem::Specification.new do |s|
16
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
19
  s.require_paths = ["lib"]
19
-
20
- s.add_dependency 'rails', '>= 3.0.0'
21
- s.add_development_dependency 'rspec'
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "rails", ">=3.0.0"
22
24
  end
25
+
@@ -0,0 +1,7 @@
1
+ module I18nScrewdriver
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
7
+
@@ -0,0 +1,21 @@
1
+ module I18nScrewdriver
2
+ module Rails
3
+ module Helper
4
+ def self.included(klass)
5
+ klass.send :include, InstanceMethods
6
+ end
7
+
8
+ module InstanceMethods
9
+ def _(text, options = {})
10
+ I18n.translate(I18nScrewdriver.for_key(text), options)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ ActionView::Base.send :include, I18nScrewdriver::Rails::Helper
18
+ ActionController::Base.send :include, I18nScrewdriver::Rails::Helper
19
+ ActionController::IntegrationTest.send :include, I18nScrewdriver::Rails::Helper
20
+ ActionController::TestCase.send :include, I18nScrewdriver::Rails::Helper
21
+
@@ -0,0 +1,4 @@
1
+ require 'rails'
2
+ require 'i18n_screwdriver/rails/engine'
3
+ require 'i18n_screwdriver/rails/helper'
4
+
@@ -0,0 +1,4 @@
1
+ module I18nScrewdriver
2
+ VERSION = "1.0.0"
3
+ end
4
+
@@ -1,33 +1,35 @@
1
- # encoding: utf-8
1
+ require "i18n_screwdriver/version"
2
+ require "i18n_screwdriver/rails"
2
3
 
3
- require 'action_view'
4
- require 'action_controller'
5
- require 'i18n/screwdriver/scanner'
4
+ module I18nScrewdriver
5
+ def self.filename(locale)
6
+ "config/locales/application.#{locale}.yml"
7
+ end
8
+
9
+ def self.for_key(string)
10
+ string.gsub(/\./, "").strip
11
+ end
6
12
 
7
- module I18n
8
- module Screwdriver
9
- def self.included(klass)
10
- klass.send :include, InstanceMethods
13
+ def self.load_translations(locale)
14
+ filename = self.filename(locale)
15
+ raise "File #{filename} not found!" unless File.exists?(filename)
16
+ YAML.load_file(filename)[locale]
17
+ end
18
+
19
+ def self.write_translations(locale, translations)
20
+ File.open(filename(locale), "w") do |file|
21
+ file.puts "# use rake task i18n:update to generate this file"
22
+ file.puts
23
+ file.puts({locale => translations}.to_yaml)
24
+ file.puts
11
25
  end
12
-
13
- module InstanceMethods
14
- def _(translation)
15
- # the . is a special character in rails i18n - we have to strip it
16
- translation_without_dot = translation.gsub(/\./, '').strip
17
- translated = I18n.translate(translation_without_dot)
18
-
19
- if defined?(Rails) && Rails.env.development? && translated.start_with?('translation missing')
20
- # TODO: add translation with key to all translation files
21
- # so that rake task is obsolete - instant feedback!
22
- end
23
-
24
- translated
25
- end
26
+ end
27
+
28
+ def self.grab_texts_to_be_translated(string)
29
+ [].tap do |texts|
30
+ texts.concat(string.scan(/_\("([^"]+)"\)/).map{ |v| v[0] })
31
+ texts.concat(string.scan(/_\('([^']+)'\)/).map{ |v| v[0] })
26
32
  end
27
33
  end
28
34
  end
29
35
 
30
- ActionView::Base.send :include, I18n::Screwdriver
31
- ActionController::Base.send :include, I18n::Screwdriver
32
- ActionController::IntegrationTest.send :include, I18n::Screwdriver
33
- ActionController::TestCase.send :include, I18n::Screwdriver
data/lib/tasks/i18n.rake CHANGED
@@ -1,14 +1,68 @@
1
1
  namespace :i18n do
2
- desc 'update translation files'
2
+ desc 'Find all translations in views, helpers and controllers'
3
3
  task :update => :environment do
4
- I18n::Screwdriver::Scanner.new.run
4
+ raise "Please set I18.default_locale" unless I18n.default_locale.present?
5
+ default_locale = I18n.default_locale.to_s
6
+
7
+ raise "Please set I18.available_locales" unless I18n.available_locales.count > 0
8
+ available_locales = I18n.available_locales.map(&:to_s)
9
+
10
+ # parse all view files for texts to be translated
11
+ texts = []
12
+ Dir.glob("**/*.{haml,erb,slim}").each do |file|
13
+ texts.concat(I18nScrewdriver.grab_texts_to_be_translated(File.read(file)))
14
+ end
15
+
16
+ # also check helper files and controllers
17
+ Dir.glob("**/*{_helper,_controller}.rb").each do |file|
18
+ texts.concat(I18nScrewdriver.grab_texts_to_be_translated(File.read(file)))
19
+ end
20
+
21
+ # remove duplicates
22
+ texts.uniq!
23
+
24
+ # transform translations into a hash, sanitizing the keys
25
+ translations = {}
26
+ texts.each{ |text| translations[I18nScrewdriver.for_key(text)] = text }
27
+
28
+ # rewrite default language file with updated translations
29
+ puts "Found #{translations.keys.size} unique translations"
30
+ I18nScrewdriver.write_translations(default_locale, translations)
31
+
32
+ # process each language we'd like to translate
33
+ (available_locales - [default_locale]).each do |locale|
34
+ filename = I18nScrewdriver.filename(locale)
35
+
36
+ # load existing translations
37
+ existing_translations = File.exists?(filename) ? I18nScrewdriver.load_translations(locale) : {}
38
+
39
+ # delete removed translations from hash
40
+ existing_translations.reject!{ |k| !translations.has_key?(k) }
41
+
42
+ # add new translations
43
+ translations.each_key{ |k| existing_translations[k] ||= "TRANSLATION_MISSING" }
44
+
45
+ # write the file
46
+ I18nScrewdriver.write_translations(locale, existing_translations)
47
+ end
5
48
  end
6
-
7
- desc 'translate foreign language file line by line'
49
+
50
+ desc 'Translate all not yet translated texts for a given locale'
8
51
  task :translate => :environment do
9
- language = ENV['TRANSLATE'] || FOREIGN_LANGUAGES.first
10
- raise "ERROR: usage: TRANSLATE=de rake i18n:translate" unless language
11
-
12
- I18n::Screwdriver::Scanner.new.translate(language)
52
+ raise "ERROR: usage: TRANSLATE=de rake i18n:translate" unless ENV['TRANSLATE']
53
+ locale = ENV['TRANSLATE']
54
+
55
+ translations = I18nScrewdriver.load_translations(locale)
56
+ puts "Translating #{translations.keys.size} entries to <#{locale}> (enter :q to save and quit):"
57
+ translations.keys.sort.each do |key|
58
+ next unless ["TRANSLATION_MISSING", ""].include?(translations[key])
59
+ puts "> #{key}"
60
+ input = STDIN.gets.chomp
61
+ break if input == ":q"
62
+ translations[key] = input
63
+ end
64
+
65
+ puts "Saving translations..."
66
+ I18nScrewdriver.write_translations(locale, translations)
13
67
  end
14
- end
68
+ end
metadata CHANGED
@@ -1,63 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n_screwdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tobias Miesel
9
+ - Corin Langosch
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2011-10-13 00:00:00.000000000 +02:00
13
- default_executable:
13
+ date: 2011-10-13 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: rails
17
- requirement: &70122007483080 !ruby/object:Gem::Requirement
16
+ name: rspec
17
+ requirement: &18220320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
21
21
  - !ruby/object:Gem::Version
22
- version: 3.0.0
23
- type: :runtime
22
+ version: '0'
23
+ type: :development
24
24
  prerelease: false
25
- version_requirements: *70122007483080
25
+ version_requirements: *18220320
26
26
  - !ruby/object:Gem::Dependency
27
- name: rspec
28
- requirement: &70122007482320 !ruby/object:Gem::Requirement
27
+ name: rails
28
+ requirement: &18219700 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
33
+ version: 3.0.0
34
+ type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70122007482320
36
+ version_requirements: *18219700
37
37
  description: make translating with rails i18n fun again
38
38
  email:
39
39
  - agileapplications@gmail.com
40
+ - info@corinlangosch.com
40
41
  executables: []
41
42
  extensions: []
42
43
  extra_rdoc_files: []
43
44
  files:
44
- - .bundle/config
45
45
  - .gitignore
46
- - .rvmrc
47
46
  - Gemfile
48
47
  - Gemfile.lock
49
48
  - README.rdoc
50
49
  - Rakefile
51
50
  - i18n_screwdriver.gemspec
52
- - lib/generators/screwdriver_generator.rb
53
- - lib/i18n/screwdriver/scanner.rb
54
51
  - lib/i18n_screwdriver.rb
52
+ - lib/i18n_screwdriver/rails.rb
53
+ - lib/i18n_screwdriver/rails/engine.rb
54
+ - lib/i18n_screwdriver/rails/helper.rb
55
+ - lib/i18n_screwdriver/version.rb
55
56
  - lib/tasks/i18n.rake
56
- - spec/libraries/i18n_screwdriver_spec.rb
57
- - spec/libraries/scanner_spec.rb
58
- - spec/spec_helper.rb
59
- has_rdoc: true
60
- homepage: http://github.com/agileapplications/i18n_screwdriver
57
+ homepage: https://github.com/agileapplications/i18n_screwdriver
61
58
  licenses: []
62
59
  post_install_message:
63
60
  rdoc_options: []
@@ -77,11 +74,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
74
  version: '0'
78
75
  requirements: []
79
76
  rubyforge_project: i18n_screwdriver
80
- rubygems_version: 1.6.2
77
+ rubygems_version: 1.8.8
81
78
  signing_key:
82
79
  specification_version: 3
83
80
  summary: make translating with rails i18n fun again
84
- test_files:
85
- - spec/libraries/i18n_screwdriver_spec.rb
86
- - spec/libraries/scanner_spec.rb
87
- - spec/spec_helper.rb
81
+ test_files: []
data/.bundle/config DELETED
@@ -1,2 +0,0 @@
1
- --- {}
2
-
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm 1.9.2
@@ -1,5 +0,0 @@
1
- class ScrewdriverGenerator < Rails::Generators::Base
2
- def generate_screwdriver
3
- copy_file "#{File.expand_path('../../tasks', __FILE__)}/i18n.rake", "lib/tasks/i18n.rake"
4
- end
5
- end
@@ -1,119 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module I18n
4
- module Screwdriver
5
- class Scanner
6
-
7
- PATH_TO_LOCALES = "config/locales/"
8
- LOCALE_PREFIX = "application"
9
-
10
- def initialize
11
- raise "ERROR: FOREIGN_LANGUAGES is not defined" unless defined? FOREIGN_LANGUAGES
12
- raise "ERROR: DEFAULT_LANGUAGE is not defined" unless defined? DEFAULT_LANGUAGE
13
-
14
- @translations = {}
15
- end
16
-
17
- def run
18
- scan_files
19
- write_translation_file(@translations, DEFAULT_LANGUAGE)
20
-
21
- FOREIGN_LANGUAGES.each do |language|
22
- update_translations(language)
23
- end
24
-
25
- puts "#{@translations.keys.length} unique translations found"
26
- end
27
-
28
- def translate(language)
29
- file_name = PATH_TO_LOCALES + LOCALE_PREFIX + ".#{language}.yml"
30
- raise "File #{file_name} not found!" unless File.exists?(file_name)
31
- existing_translations = YAML.load_file(file_name)[language]
32
-
33
- existing_translations.each do |key, translation|
34
- if translation.length == 0
35
- puts "> #{key}"
36
- input = STDIN.gets.chomp
37
- if input == ":q"
38
- break
39
- else
40
- existing_translations[key] = input
41
- end
42
- end
43
- end
44
-
45
- write_translation_file(existing_translations, language)
46
- end
47
-
48
-
49
- private
50
-
51
- def update_translations(language)
52
- existing_translations = {}
53
- file_name = PATH_TO_LOCALES + LOCALE_PREFIX + ".#{language}.yml"
54
- existing_translations = YAML.load_file(file_name)[language] if File.exists?(file_name)
55
-
56
- syncronize_translations(existing_translations)
57
- write_translation_file(existing_translations, language)
58
- end
59
-
60
- def syncronize_translations(existing_translations)
61
- @translations.each_key do |key|
62
- existing_translations[key] = "" unless existing_translations.has_key?(key)
63
- end
64
- existing_translations
65
- end
66
-
67
- def scan_files
68
- Dir.glob("**/*.{haml,erb,slim,rb}").each do |file_name|
69
- scan_file(file_name)
70
- end
71
- end
72
-
73
- def scan_file(file_name)
74
- File.open(file_name) do |file|
75
- file.each do |line|
76
- @translations.merge!(extract_translation(line))
77
- end
78
- end
79
- end
80
-
81
- def extract_translation(line)
82
- {}.tap do |hash|
83
- if line =~ /_\("([^"]+)"\)/
84
- hash[translation_to_key($1)] = $1
85
- elsif line =~ /_\('([^']+)'\)/
86
- hash[translation_to_key($1)] = $1
87
- end
88
- end
89
- end
90
-
91
- def sorted_translations(translations)
92
- translations.keys.sort do |a, b|
93
- a.downcase <=> b.downcase
94
- end.each do |key|
95
- yield key, translations[key]
96
- end
97
- end
98
-
99
- def translation_to_key(translation)
100
- translation.gsub(/\./, '')
101
- end
102
-
103
- def remove_translation(key)
104
- @translations.delete(key) #unless translations.has_key?(key)
105
- end
106
-
107
- def write_translation_file(translations, language)
108
- File.open("config/locales/application.#{language}.yml", "w") do |file|
109
- file.puts "# use rake task i18n:update to update this file"
110
- file.puts
111
- file.puts "\"#{language}\":"
112
- sorted_translations(translations) do |key, translation|
113
- file.puts " \"#{key}\": \"#{translation}\""
114
- end
115
- end
116
- end
117
- end
118
- end
119
- end
@@ -1,11 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe I18n::Screwdriver do
4
-
5
- describe "translation helper" do
6
- it "removes dots from translation string" do
7
- _("my.new.translation").should == "translation missing: en.mynewtranslation"
8
- end
9
- end
10
-
11
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe I18n::Screwdriver::Scanner do
4
-
5
- before do
6
- @scanner = I18n::Screwdriver::Scanner.new
7
- end
8
-
9
- describe "extract_translation" do
10
- it "returns an empty hash when no translation was found" do
11
- @scanner.send(:extract_translation, 'hello world').should == {}
12
- end
13
-
14
- it "returns a filled hash when translation was found" do
15
- @scanner.send(:extract_translation, '_("hello world")').should == {
16
- 'hello world' => 'hello world'
17
- }
18
-
19
- @scanner.send(:extract_translation, '_("Going out today.")').should == {
20
- 'Going out today' => 'Going out today.'
21
- }
22
-
23
- @scanner.send(:extract_translation, '_(".a.b.c.d.e")').should == {
24
- 'abcde' => '.a.b.c.d.e'
25
- }
26
- end
27
- end
28
-
29
- describe "translation_to_key" do
30
- it "removes all dots" do
31
- @scanner.send(:translation_to_key, 'Good morning.').should == 'Good morning'
32
- end
33
- end
34
-
35
- describe "sorted_translations" do
36
- it "returns all translations sorted" do
37
- #@scanner.send(:sorted_translations) do |key, translation|
38
- # puts " \"#{key}\": \"#{translation}\""
39
- #end
40
- end
41
- end
42
-
43
- end
data/spec/spec_helper.rb DELETED
@@ -1,13 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- require 'i18n_screwdriver'
5
-
6
- DEFAULT_LANGUAGE = 'de'
7
- FOREIGN_LANGUAGES = ['en']
8
-
9
- RSpec.configure do |config|
10
-
11
- config.include I18n::Screwdriver
12
-
13
- end