i18n_generators 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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