i18n_generators 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +1 -0
  2. data/History.txt +104 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +104 -0
  5. data/Rakefile +38 -0
  6. data/VERSION +1 -0
  7. data/generators/i18n/USAGE +13 -0
  8. data/generators/i18n/i18n_generator.rb +85 -0
  9. data/generators/i18n/lib/yaml.rb +187 -0
  10. data/generators/i18n/templates/base.yml +0 -0
  11. data/generators/i18n/templates/i18n_config.rb +5 -0
  12. data/generators/i18n/templates/translation.yml +1 -0
  13. data/generators/i18n_locale/USAGE +12 -0
  14. data/generators/i18n_locale/i18n_locale_command.rb +135 -0
  15. data/generators/i18n_locale/i18n_locale_generator.rb +9 -0
  16. data/generators/i18n_locale/lib/cldr.rb +139 -0
  17. data/generators/i18n_scaffold/i18n_scaffold_generator.rb +3 -0
  18. data/generators/i18n_scaffold/templates/controller.rb +85 -0
  19. data/generators/i18n_scaffold/templates/functional_test.rb +45 -0
  20. data/generators/i18n_scaffold/templates/helper.rb +2 -0
  21. data/generators/i18n_scaffold/templates/helper_test.rb +4 -0
  22. data/generators/i18n_scaffold/templates/layout.html.erb +17 -0
  23. data/generators/i18n_scaffold/templates/style.css +54 -0
  24. data/generators/i18n_scaffold/templates/view_edit.html.erb +18 -0
  25. data/generators/i18n_scaffold/templates/view_index.html.erb +24 -0
  26. data/generators/i18n_scaffold/templates/view_new.html.erb +17 -0
  27. data/generators/i18n_scaffold/templates/view_show.html.erb +10 -0
  28. data/generators/i18n_translation/USAGE +9 -0
  29. data/generators/i18n_translation/i18n_translation_command.rb +121 -0
  30. data/generators/i18n_translation/i18n_translation_generator.rb +9 -0
  31. data/generators/i18n_translation/lib/erb_executer.rb +31 -0
  32. data/generators/i18n_translation/lib/recording_backend.rb +16 -0
  33. data/generators/i18n_translation/lib/through_ryoku.rb +8 -0
  34. data/generators/i18n_translation/lib/translator.rb +28 -0
  35. data/i18n_generators.gemspec +87 -0
  36. data/spec/cldr_spec.rb +54 -0
  37. data/spec/data/cldr/ja.html +3112 -0
  38. data/spec/data/yml/active_record/en-US.yml +54 -0
  39. data/spec/i18n_locale_command_spec.rb +63 -0
  40. data/spec/i18n_translation_command_spec.rb +24 -0
  41. data/spec/spec_helper.rb +39 -0
  42. data/spec/translator_spec.rb +46 -0
  43. data/spec/yaml_spec.rb +59 -0
  44. metadata +114 -0
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/History.txt ADDED
@@ -0,0 +1,104 @@
1
+ == 0.8.0
2
+
3
+ * major enhancements:
4
+ * Gemify
5
+
6
+ == 0.7.0
7
+
8
+ * major enhancements:
9
+ * Fix gettext dependency version
10
+ * enhancements:
11
+ * Add more error checks when loading models
12
+ * Load gettext only when using it
13
+
14
+ == 0.6.0
15
+
16
+ * bugfixes:
17
+ * Could not load cldr data with short locale names
18
+ * major enhancements:
19
+ * Include AR association names in model attributes translation
20
+ * Add 'generated' comment mark (#g) for generated lines in YAML (thanks to t-wada-senpai, Shimura-san, Toyofuku-san, Sezutsu-san and oukayuka-san!)
21
+ * Add --include-timestamps option and change default bahaviour not to include timestamp columns in translation YAML
22
+ * Add blank line between each blocks (thanks to Sawayanagi-san!)
23
+ * enhancements:
24
+ * Avoid generating blank locale file
25
+ * Change GitHub fetch URL from blob/master/...?raw=true to raw/master
26
+
27
+ == 0.5.0
28
+
29
+ * bugfixes:
30
+ * Could not fetch the locale files via GitHub (GitHub changed the URL?)
31
+ * major enhancements:
32
+ * Ruby 1.9 ready!
33
+ * Never connect to CLDR site when the locale file found in Sven's rails-i18n repository
34
+ * enhancements:
35
+ * Use Ruby 1.9 built-in JSON parser if Ruby 1.9
36
+
37
+ == 0.4.1
38
+
39
+ * bugfixes:
40
+ * i18n_translation abnormally ends when loading a view containing "-%>" (thanks to babie-san!)
41
+
42
+ == 0.4.0
43
+
44
+ * major enhancements:
45
+ * translation generator now preserves any existing extra lines in the YAML file (thanks to Iain Hecker-san!)
46
+
47
+ == 0.3.4
48
+
49
+ * enhancements:
50
+ * Reduce unnecessary request to CLDR site
51
+
52
+ == 0.3.3
53
+
54
+ * bugfixes:
55
+ * Did not work on Ruby 1.8.6 (thanks to akm-san!)
56
+
57
+ == 0.3.2
58
+
59
+ * bugfixes:
60
+ * Trim mode in ERB didn't work on some platforms (thanks to valda-san!)
61
+
62
+ == 0.3.1
63
+
64
+ * enhancements:
65
+ * Translate all keys simultaneously using thread
66
+ * Translations with :scope is going to be yamlized with proper hierarchy
67
+
68
+ == 0.3.0
69
+
70
+ * major enhancements:
71
+ * Renamed the generators
72
+ i18n_locales -> i18n_locale (i18n --locale)
73
+ i18n_models -> i18n_translation (i18n --translation)
74
+ * Handle all translate keys which appear in view files (thanks to PanosJee-san!)
75
+
76
+ == 0.2.0
77
+
78
+ * major enhancements:
79
+ * Implemented i18n_scaffold generator (thanks to Iain Hecker-san!)
80
+
81
+ * enhancements:
82
+ * i18n_models generator can now deal with non AR classes which has content_columns (thanks to Iain Hecker-san!)
83
+
84
+ == 0.1.0
85
+
86
+ * major enhancements:
87
+ * Fetch locale YAML file from rails-i18n project repository first
88
+
89
+ * bugfixes:
90
+ * Could not recognize model names with multipie words (thanks to makoto-san!)
91
+
92
+ == 0.0.8
93
+
94
+ * major enhancements:
95
+ * Lots of changes for this commit by DHH http://github.com/rails/rails/commit/d9b92ee11b33fed5c7a94a91415fa846705f7dd3
96
+
97
+ == 0.0.4
98
+
99
+ * Gemified on GitHub
100
+
101
+ == 0.0.1
102
+
103
+ * Birthday!
104
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,104 @@
1
+ = I18n generators
2
+
3
+ This gem plugin generates a set of locale files for Rails 2.2 i18n feature.
4
+
5
+ * http://github.com/amatsuda/i18n_generators/tree/master
6
+
7
+
8
+ == FEATURES
9
+
10
+ This gem/plugin provides following four script/generate commands.
11
+
12
+ === 1. Generate I18n Scaffold
13
+
14
+ % ./script/generate i18n_scaffold ja (de-AT, pt-BR, etc.)
15
+
16
+ Generates I18n aware scaffold.
17
+
18
+ === 2. Generate Locale Files for ActiveRecord/ActiveSupport/ActionPack
19
+
20
+ % ./script/generate i18n_locale ja (de-AT, pt-BR, etc.)
21
+
22
+ or
23
+
24
+ % ./script/generate i18n --locale ja (de-AT, pt-BR, etc.)
25
+
26
+ * A. If The Locale File Exists In Rails-I18n Repository
27
+
28
+ Firstly, the generator checks here.
29
+ http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale
30
+ If the spacified .yml file exists in the repository, the generator downloads and puts the file into your config/locales directory.
31
+ Then the generater sets the application default locale to the specified locale.
32
+
33
+ This will generate following locale file.
34
+
35
+ config/locales/ja.yml
36
+
37
+ * B. Else
38
+
39
+ The generator copies the en.yml file (bundled inside Rails framework) into config/locales directory, and one-to-one localizes/translates each attribute value into the specified locale/language.
40
+ Then the generater sets the application default locale to the specified locale.
41
+
42
+ For example,
43
+
44
+ % ./script/generate i18n_locale zh
45
+
46
+ will generate following locale files.
47
+
48
+ config/locales/active_support_zh.yml
49
+ config/locales/active_record_zh.yml
50
+ config/locales/action_view_zh.yml
51
+
52
+ === 3. Generate Translation YAML File For All Models/Attributes and views/**/*.erb
53
+
54
+ % ./script/generate i18n_translation ja (de-AT, pt-BR, etc.)
55
+
56
+ or
57
+
58
+ % ./script/generate i18n --translation ja (de-AT, pt-BR, etc.)
59
+
60
+ This will generate following YAML file.
61
+
62
+ config/locales/translation_ja.yml
63
+
64
+ The generator scans your app/models directory, and generates a YAML file with all the AR model names and attributes so that you don't have to write the YAML skeleton manually or by copy/paste.
65
+ In addition, the generator scans all the *.erb files in your app/views/** directory, and picks all the keys for I18n.translate, then adds them to the YAML file.
66
+ In addition, the generator tries to translate each of them into the specified language.
67
+ The generator doesn't overwrite the existing value so that you can rerun the generator again and again just like Annotate Model command.
68
+
69
+ === 4. Generate All
70
+
71
+ % ./script/generate i18n ja (de-AT, pt-BR, etc.)
72
+
73
+ Executes 2 and 3 at once.
74
+
75
+
76
+ == REQUIREMENTS:
77
+
78
+ * Ruby on Rails (>= 2.2)
79
+ * Ruby-GetText-Package ( http://rubyforge.org/projects/gettext/ )
80
+ * high speed Internet connection
81
+
82
+
83
+ == INSTALL:
84
+
85
+ * As a gem
86
+
87
+ % sudo gem source http://gems.github.com
88
+
89
+ % sudo gem install amatsuda-i18n_generators
90
+
91
+ * As a Rails plugin
92
+
93
+ % ./script/plugin install git://github.com/amatsuda/i18n_generators.git
94
+
95
+
96
+ == CAUTION
97
+
98
+ Current version of this plugin is very very very roughly implemented just for experiment.
99
+ Every time you execute the generate command, the plugin connects to the Unicode CLDR website and scrapes the huge amount of its contents.
100
+ Please be careful not to harm your network environment and CLDR website by running this plugin too many times.
101
+
102
+
103
+ Copyright (c) 2008 Akira Matsuda, released under the MIT license
104
+
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ # require 'spec/rake/spectask'
6
+
7
+ desc 'Default: run the specs.'
8
+ task :default => :spec
9
+
10
+ # desc 'Run the specs for i18n_generators.'
11
+ # Spec::Rake::SpecTask.new(:spec) do |t|
12
+ # t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
13
+ # t.spec_files = FileList['spec/**/*_spec.rb']
14
+ # end
15
+
16
+ desc 'Generate documentation for the i18n_generators plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'I18nGenerators'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README.rdoc')
22
+ rdoc.rdoc_files.include('generators/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = 'i18n_generators'
29
+ gemspec.summary = 'Generates I18n locale files for Rails 2.2 and 2.3'
30
+ gemspec.description = 'A Rails generator plugin & gem that generates Rails 2.2 and 2.3 I18n locale files for almost every known locale.'
31
+ gemspec.email = 'ronnie@dio.jp'
32
+ gemspec.homepage = 'http://github.com/amatsuda/i18n_generators/'
33
+ gemspec.authors = ['Akira Matsuda']
34
+ end
35
+ Jeweler::GemcutterTasks.new
36
+ rescue LoadError
37
+ puts 'Jeweler not available. Install it with: gem install jeweler'
38
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.0
@@ -0,0 +1,13 @@
1
+ Description:
2
+ Generates a config file and locale files and a model/attributes translation file for Rails i18n feature.
3
+
4
+ Example:
5
+ ./script/generate i18n locale_name (ja-JP, de-AT, etc.)
6
+
7
+ This will create:
8
+ config/initializers/i18n_config.rb
9
+ lib/locale/action_view_ja-JP.yml
10
+ lib/locale/active_record_ja-JP.yml
11
+ lib/locale/active_support_ja-JP.yml
12
+ lib/locale/models_ja-JP.yml
13
+
@@ -0,0 +1,85 @@
1
+ require 'rubygems'
2
+ require 'rails_generator'
3
+ require 'rails_generator/commands'
4
+
5
+ class I18nGenerator < Rails::Generator::NamedBase
6
+ attr_reader :locale_name, :cldr, :translator, :generate_translation_only, :generate_locale_only, :include_timestamps
7
+
8
+ def initialize(runtime_args, runtime_options = {})
9
+ if options[:scaffold]
10
+ #TODO invoke scaffold generator
11
+ puts 'please use generate i18n_scaffold command'
12
+ exit
13
+ end
14
+
15
+ super
16
+ unless name =~ /^[a-zA-Z]{2}([-_][a-zA-Z]{2})?$/
17
+ puts 'ERROR: Wrong locale format. Please input in ?? or ??-?? format.'
18
+ exit
19
+ end
20
+ @locale_name = name.length == 5 ? "#{name[0..1].downcase}-#{name[3..4].upcase}" : "#{name[0..1].downcase}"
21
+
22
+ unless options[:generate_translation_only]
23
+ gem 'gettext', '<2'
24
+ require 'gettext'
25
+ @cldr = CldrDocument.new @locale_name
26
+ GetText.bindtextdomain 'rails'
27
+ GetText.locale = @locale_name
28
+ end
29
+ unless options[:generate_locale_only]
30
+ lang = @locale_name.sub(/-.*$/, '')
31
+ @translator = Translator.new lang
32
+ end
33
+ @include_timestamps = true if options[:include_timestamps]
34
+ end
35
+
36
+ def manifest
37
+ record do |m|
38
+ m.directory 'config/locales'
39
+ unless options[:generate_translation_only]
40
+ logger.debug 'updating environment.rb ...'
41
+ m.generate_configuration
42
+ if defined_in_rails_i18n_repository?
43
+ logger.debug "fetching #{locale_name}.yml from rails-i18n repository..."
44
+ m.fetch_from_rails_i18n_repository
45
+ else
46
+ logger.debug "generating #{locale_name} YAML files for Rails..."
47
+ m.active_support_yaml
48
+ m.active_record_yaml
49
+ m.action_view_yaml
50
+ end
51
+ end
52
+ unless options[:generate_locale_only]
53
+ m.translation_yaml
54
+ end
55
+ end
56
+ end
57
+
58
+ protected
59
+ def add_options!(opt)
60
+ opt.separator ''
61
+ opt.separator 'Options:'
62
+ opt.on('--translation',
63
+ 'Generate translations for all models with their attributes and all translation keys in the view files.') {|v| options[:generate_translation_only] = v}
64
+ opt.on('--locale', 'Generate locale files.') {|v| options[:generate_locale_only] = v}
65
+ opt.on('--include-timestamps', 'Include timestamp columns in the YAML translation.') {|v| options[:include_timestamps] = v}
66
+ opt.on('--include-timestamp', 'Include timestamp columns in the YAML translation.') {|v| options[:include_timestamps] = v}
67
+ end
68
+
69
+ private
70
+ def defined_in_rails_i18n_repository?
71
+ begin
72
+ uri = "http://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/#{locale_name}.yml"
73
+ OpenURI.open_uri(uri) do |res|
74
+ (res.base_uri.to_s == uri) && (res.status == %w[200 OK])
75
+ end
76
+ rescue
77
+ false
78
+ end
79
+ end
80
+ end
81
+
82
+ require File.join(File.dirname(__FILE__), '../i18n_locale/i18n_locale_command')
83
+ require File.join(File.dirname(__FILE__), '../i18n_translation/i18n_translation_command')
84
+ Rails::Generator::Commands::Create.send :include, I18nGenerator::Generator::Commands::Create
85
+
@@ -0,0 +1,187 @@
1
+ require 'yaml'
2
+
3
+ module I18nLocaleGeneratorModule
4
+ class Node
5
+ attr_reader :document, :indent_level
6
+ attr_accessor :line
7
+
8
+ def initialize(parent, line_index, text)
9
+ @document, @line, @text = parent.document, line_index, text.to_s
10
+ @text =~ /(^\s*)/
11
+ @indent_level = $1.nil? ? 0 : $1.size
12
+ @yaml = YAML.load(@text.to_s + ' ')
13
+ end
14
+
15
+ def parent
16
+ @parent ||= document.parent_of self
17
+ end
18
+
19
+ def children
20
+ @children ||= document.children_of(self)
21
+ end
22
+ alias :nodes :children
23
+
24
+ def [](node_name)
25
+ if node = nodes.detect {|n| n.key.to_s == node_name.to_s}
26
+ node
27
+ else
28
+ nodes.add "#{' ' * (@indent_level + 2)}#{node_name}: "
29
+ nodes.last
30
+ end
31
+ end
32
+
33
+ def key
34
+ @yaml.is_a?(Hash) ? @yaml.keys.first : nil
35
+ end
36
+
37
+ def value
38
+ @yaml.is_a?(Hash) ? @yaml.values.first : nil
39
+ end
40
+
41
+ def value=(val)
42
+ if @yaml[self.key] != val
43
+ @yaml[self.key] = val
44
+ @changed = true
45
+ end
46
+ end
47
+
48
+ def text
49
+ if @changed
50
+ v = if self.value.is_a?(Array)
51
+ "[#{self.value * ', '}]"
52
+ else
53
+ %Q["#{self.value}"]
54
+ end
55
+ "#{' ' * self.indent_level}#{self.key}: #{v} #g" # g is for 'generated'!
56
+ else
57
+ @text
58
+ end
59
+ end
60
+ alias :to_s :text
61
+
62
+ def changed?
63
+ @changed
64
+ end
65
+
66
+ def is_blank_or_comment?
67
+ @text.sub(/#.*$/, '').gsub(/\s/, '').empty?
68
+ end
69
+
70
+ def path
71
+ @path ||= "#{self.parent.path}/#{self.key}"
72
+ end
73
+
74
+ def descendant_nodes(&block)
75
+ yield self if self.value
76
+ self.children.each {|child| child.descendant_nodes(&block)} if self.children
77
+ end
78
+
79
+ def <=>(other)
80
+ self.line <=> other.line
81
+ end
82
+ end
83
+
84
+ class YamlDocument < Node
85
+ attr_accessor :lines
86
+ alias :nodes :lines
87
+
88
+ def initialize(yml_path, locale_name)
89
+ @locale_name, @lines, @current_line, @indent_level = locale_name, Nodes.new(self), -1, -2
90
+ if File.exists? yml_path
91
+ File.open(yml_path) do |file|
92
+ file.each_with_index do |line_text, i|
93
+ n = Node.new(self, i, line_text.chomp)
94
+ @lines << ((((n.key == 'en-US') || (n.key == 'en')) && n.value.blank?) ? Node.new(self, i, "#{locale_name}:") : n)
95
+ end
96
+ @lines.delete_at(-1) if @lines[-1].text.blank?
97
+ end
98
+ end
99
+ end
100
+
101
+ def next
102
+ return false if @lines.size == 0
103
+ @current_line += 1
104
+ return false if @current_line >= @lines.size
105
+ @lines[@current_line].is_blank_or_comment? ? self.next : @lines[@current_line]
106
+ end
107
+
108
+ def prev
109
+ return false if @current_line == 0
110
+ @current_line -= 1
111
+ @lines[@current_line].is_blank_or_comment? ? self.prev : @lines[@current_line]
112
+ end
113
+
114
+ def parent_of(child)
115
+ @current_line = child.line
116
+ while n = self.prev
117
+ return n if n.indent_level == child.indent_level - 2
118
+ end
119
+ self
120
+ end
121
+
122
+ def children_of(parent)
123
+ nodes = Nodes.new(parent)
124
+ @current_line = parent.line
125
+ while n = self.next
126
+ if n.indent_level < parent.indent_level + 2
127
+ break
128
+ elsif n.indent_level == parent.indent_level + 2
129
+ nodes << n
130
+ end
131
+ end
132
+ nodes
133
+ end
134
+
135
+ def document
136
+ self
137
+ end
138
+
139
+ def path
140
+ ''
141
+ end
142
+
143
+ def line
144
+ @current_line
145
+ end
146
+
147
+ def to_s(add_blank_line = false)
148
+ previous_indent_level = 0
149
+ @lines.inject('') do |ret, n|
150
+ ret << "\n" if add_blank_line && (n.indent_level < previous_indent_level) && !n.text.blank? && !ret.ends_with?("\n\n")
151
+ previous_indent_level = n.indent_level
152
+ ret << (n.text ? n.text.rstrip : '') + "\n"
153
+ end
154
+ end
155
+ end
156
+
157
+ class Nodes < Array
158
+ def initialize(parent)
159
+ super()
160
+ @parent = parent
161
+ end
162
+
163
+ def [](index)
164
+ if index.is_a?(String) || index.is_a?(Symbol)
165
+ return self.detect {|node| node.key == index} || add(index)
166
+ end
167
+ super
168
+ end
169
+
170
+ def last_leaf
171
+ c = @parent
172
+ loop do
173
+ return c if c.children.blank?
174
+ c = c.children.last
175
+ end
176
+ end
177
+
178
+ def add(node_name)
179
+ target_line = self.last_leaf.line + 1
180
+ @parent.document.nodes.each {|n| n.line += 1 if n.line >= target_line}
181
+ node = Node.new(@parent, target_line, node_name)
182
+ @parent.document.lines << node
183
+ @parent.document.lines.sort!
184
+ self << node unless @parent.is_a? YamlDocument
185
+ end
186
+ end
187
+ end