haml-magic-translations 0.2.2 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -0
- data/README.rdoc +18 -2
- data/Rakefile +18 -14
- data/VERSION +1 -1
- data/haml-magic-translations.gemspec +45 -30
- data/lib/haml/magic_translations.rb +136 -89
- data/lib/haml/magic_translations/rgettext/haml_parser.rb +147 -0
- data/lib/haml/magic_translations/tasks.rb +83 -0
- data/spec/haml/magic_translations/rgettext/haml_parser_spec.rb +209 -0
- data/spec/haml/magic_translations/tasks_spec.rb +105 -0
- data/spec/haml/magic_translations_spec.rb +256 -0
- data/spec/locales/en.po +4 -0
- data/spec/locales/pl.po +10 -0
- data/spec/spec_helper.rb +3 -1
- metadata +114 -20
- data/TODO +0 -3
- data/spec/magic_translations/i18n_spec.rb +0 -65
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -27,9 +27,9 @@ To use automatical translations you have to using new I18n with Gettext backend,
|
|
27
27
|
GetText or FastGettext, properly installed and configured. To enable plugin
|
28
28
|
you have to do following things:
|
29
29
|
|
30
|
-
Haml::
|
30
|
+
Haml::MagicTranslations.enable(:i18n) # this backend is used by default
|
31
31
|
|
32
|
-
Available backends are
|
32
|
+
Available backends are +:i18n+, +:gettext+ and +:fast_gettext+
|
33
33
|
|
34
34
|
Now you have to add path to all your .po files with locales. Eg. for i18n backend
|
35
35
|
it will be something like:
|
@@ -79,7 +79,23 @@ Generator for .po files also includes information where your phrases are placed
|
|
79
79
|
in filesystem. Thanks to it you don't forget about any even small word to
|
80
80
|
translate.
|
81
81
|
|
82
|
+
=== Extracting strings and merging translations
|
83
|
+
|
84
|
+
In order to extract translatable strings and merge with existing translation,
|
85
|
+
this gem provides an Haml parser for RGetText. You can either use it directly
|
86
|
+
or through the provided Rake task. Here's an example on how to use the later:
|
87
|
+
|
88
|
+
Haml::MagicTranslations::Tasks::UpdatePoFiles.new do |t|
|
89
|
+
t.text_domain = 'my_project'
|
90
|
+
t.files = Dir.glob("views/**/*.{rb,haml}") << "lib/my_project.rb"
|
91
|
+
t.app_version = 'my_project 0.1'
|
92
|
+
end
|
93
|
+
|
94
|
+
This will add a +update_pofiles+ task that will update PO files that can be
|
95
|
+
found in the +po+ directory.
|
96
|
+
|
82
97
|
=== Copyrights
|
83
98
|
|
84
99
|
Kriss Kowalik (kriss.kowalik@gmail.com)
|
85
100
|
|
101
|
+
potager.org (jardiniers@potager.org)
|
data/Rakefile
CHANGED
@@ -15,33 +15,37 @@ find all phrases to translate and generate .po files for it. This type of files
|
|
15
15
|
are also more readable and easier to translate, thanks to it you save your
|
16
16
|
time with translations.
|
17
17
|
DESCR
|
18
|
-
gem.email = "
|
19
|
-
gem.homepage = "http://github.com/
|
20
|
-
gem.authors = ["Kriss Kowalik"]
|
21
|
-
gem.
|
18
|
+
gem.email = "jardiniers@potager.org"
|
19
|
+
gem.homepage = "http://github.com/potager/haml-magic-translations"
|
20
|
+
gem.authors = ["Kriss Kowalik", "potager.org"]
|
21
|
+
gem.add_dependency "haml", ">= 3.1.0"
|
22
|
+
gem.add_development_dependency "actionpack"
|
23
|
+
gem.add_development_dependency "gettext"
|
24
|
+
gem.add_development_dependency "fast_gettext"
|
25
|
+
gem.add_development_dependency "rspec", ">= 2"
|
26
|
+
gem.add_development_dependency "rdoc", ">= 2.4.2"
|
27
|
+
gem.add_development_dependency "maruku"
|
22
28
|
end
|
23
29
|
Jeweler::GemcutterTasks.new
|
24
30
|
rescue LoadError
|
25
31
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
26
32
|
end
|
27
33
|
|
28
|
-
require '
|
29
|
-
require '
|
34
|
+
require 'rspec/core/rake_task'
|
35
|
+
require 'rdoc/task'
|
30
36
|
|
31
37
|
desc 'Default: run specs.'
|
32
38
|
task :default => :spec
|
33
39
|
|
34
40
|
desc 'Run the specs'
|
35
|
-
|
36
|
-
t.
|
37
|
-
t.spec_opts = %w(-fs --color)
|
41
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
42
|
+
t.rspec_opts = %w(-fs --color)
|
38
43
|
end
|
39
44
|
|
40
45
|
namespace :spec do
|
41
46
|
desc "Run all specs with RCov"
|
42
|
-
|
43
|
-
t.
|
44
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
47
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
48
|
+
t.rspec_opts = ['--colour --format progress --loadby mtime --reverse']
|
45
49
|
t.rcov = true
|
46
50
|
t.rcov_opts = ['--exclude', 'spec,/Users/']
|
47
51
|
end
|
@@ -52,6 +56,6 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
52
56
|
rdoc.rdoc_dir = 'rdoc'
|
53
57
|
rdoc.title = 'SimpleNavigation'
|
54
58
|
rdoc.options << '--line-numbers' << '--inline-source'
|
55
|
-
rdoc.
|
56
|
-
rdoc.rdoc_files.include(
|
59
|
+
rdoc.main = "README.rdoc"
|
60
|
+
rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
57
61
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{haml-magic-translations}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Kriss Kowalik"]
|
12
|
-
s.date = %q{
|
11
|
+
s.authors = ["Kriss Kowalik", "potager.org"]
|
12
|
+
s.date = %q{2012-04-09}
|
13
13
|
s.description = %q{This plugin provides "magical translations" in your .haml files. What does it
|
14
14
|
mean? It's mean that all your raw texts in templates will be automatically
|
15
15
|
translated by GetText, FastGettext or Gettext backend from I18n. No more
|
@@ -19,48 +19,63 @@ find all phrases to translate and generate .po files for it. This type of files
|
|
19
19
|
are also more readable and easier to translate, thanks to it you save your
|
20
20
|
time with translations.
|
21
21
|
}
|
22
|
-
s.email = %q{
|
22
|
+
s.email = %q{jardiniers@potager.org}
|
23
23
|
s.extra_rdoc_files = [
|
24
24
|
"LICENSE",
|
25
|
-
|
26
|
-
"TODO"
|
25
|
+
"README.rdoc"
|
27
26
|
]
|
28
27
|
s.files = [
|
29
28
|
"LICENSE",
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
29
|
+
"README.rdoc",
|
30
|
+
"Rakefile",
|
31
|
+
"VERSION",
|
32
|
+
"haml-magic-translations.gemspec",
|
33
|
+
"init.rb",
|
34
|
+
"lib/haml-magic-translations.rb",
|
35
|
+
"lib/haml/magic_translations.rb",
|
36
|
+
"lib/haml/magic_translations/rgettext/haml_parser.rb",
|
37
|
+
"lib/haml/magic_translations/tasks.rb",
|
38
|
+
"spec/haml/magic_translations/rgettext/haml_parser_spec.rb",
|
39
|
+
"spec/haml/magic_translations/tasks_spec.rb",
|
40
|
+
"spec/haml/magic_translations_spec.rb",
|
41
|
+
"spec/locales/en.po",
|
42
|
+
"spec/locales/pl.po",
|
43
|
+
"spec/spec_helper.rb"
|
42
44
|
]
|
43
|
-
s.homepage = %q{http://github.com/
|
44
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
45
|
+
s.homepage = %q{http://github.com/potager/haml-magic-translations}
|
45
46
|
s.require_paths = ["lib"]
|
46
|
-
s.rubygems_version = %q{1.3.
|
47
|
+
s.rubygems_version = %q{1.3.7}
|
47
48
|
s.summary = %q{Provides automaticaly translations in haml templates}
|
48
|
-
s.test_files = [
|
49
|
-
"spec/spec_helper.rb",
|
50
|
-
"spec/magic_translations/i18n_spec.rb"
|
51
|
-
]
|
52
49
|
|
53
50
|
if s.respond_to? :specification_version then
|
54
51
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
55
52
|
s.specification_version = 3
|
56
53
|
|
57
|
-
if Gem::Version.new(Gem::
|
58
|
-
s.
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<haml>, [">= 3.1.0"])
|
56
|
+
s.add_development_dependency(%q<actionpack>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<gettext>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<fast_gettext>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<rspec>, [">= 2"])
|
60
|
+
s.add_development_dependency(%q<rdoc>, [">= 2.4.2"])
|
61
|
+
s.add_development_dependency(%q<maruku>, [">= 0"])
|
59
62
|
else
|
60
|
-
s.add_dependency(%q<haml>, [">= 3.
|
63
|
+
s.add_dependency(%q<haml>, [">= 3.1.0"])
|
64
|
+
s.add_dependency(%q<actionpack>, [">= 0"])
|
65
|
+
s.add_dependency(%q<gettext>, [">= 0"])
|
66
|
+
s.add_dependency(%q<fast_gettext>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rspec>, [">= 2"])
|
68
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
69
|
+
s.add_dependency(%q<maruku>, [">= 0"])
|
61
70
|
end
|
62
71
|
else
|
63
|
-
s.add_dependency(%q<haml>, [">= 3.
|
72
|
+
s.add_dependency(%q<haml>, [">= 3.1.0"])
|
73
|
+
s.add_dependency(%q<actionpack>, [">= 0"])
|
74
|
+
s.add_dependency(%q<gettext>, [">= 0"])
|
75
|
+
s.add_dependency(%q<fast_gettext>, [">= 0"])
|
76
|
+
s.add_dependency(%q<rspec>, [">= 2"])
|
77
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
78
|
+
s.add_dependency(%q<maruku>, [">= 0"])
|
64
79
|
end
|
65
80
|
end
|
66
81
|
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
1
3
|
require 'haml'
|
2
|
-
require '
|
4
|
+
require 'json'
|
3
5
|
|
4
6
|
##
|
5
7
|
# This plugin provides "magical translations" in your .haml files. What does it
|
@@ -42,116 +44,161 @@ require 'haml/template'
|
|
42
44
|
module Haml::MagicTranslations
|
43
45
|
def self.included(haml) # :nodoc:
|
44
46
|
haml.send(:include, EngineMethods)
|
45
|
-
Haml::Template
|
47
|
+
if defined? Haml::Template
|
48
|
+
Haml::Template.send(:extend, TemplateMethods)
|
49
|
+
end
|
46
50
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
51
|
+
|
52
|
+
# It discovers all fragments of code embeded in text and replacing with
|
53
|
+
# simple string interpolation parameters.
|
54
|
+
#
|
55
|
+
# ==== Example:
|
56
|
+
#
|
57
|
+
# Following line...
|
58
|
+
#
|
59
|
+
# %p This is some #{'Interpolated'.upcase'} text
|
60
|
+
#
|
61
|
+
# ... will be translated to:
|
62
|
+
#
|
63
|
+
# [ "This is some %s text", "['Interpolated'.upcase]" ]
|
64
|
+
#
|
65
|
+
def self.prepare_i18n_interpolation(str, escape_html = nil)
|
66
|
+
args = []
|
67
|
+
res = ''
|
68
|
+
str = str.
|
69
|
+
gsub(/\n/, '\n').
|
70
|
+
gsub(/\r/, '\r').
|
71
|
+
gsub(/\#/, '\#').
|
72
|
+
gsub(/\"/, '\"').
|
73
|
+
gsub(/\\/, '\\\\')
|
74
|
+
|
75
|
+
rest = Haml::Shared.handle_interpolation '"' + str + '"' do |scan|
|
76
|
+
escapes = (scan[2].size - 1) / 2
|
77
|
+
res << scan.matched[0...-3 - escapes]
|
78
|
+
if escapes % 2 == 1
|
79
|
+
res << '#{'
|
63
80
|
else
|
64
|
-
|
81
|
+
content = eval('"' + Haml::Shared.balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
|
82
|
+
content = "Haml::Helpers.html_escape(#{content.to_s})" if escape_html
|
83
|
+
args << content
|
84
|
+
res << '%s'
|
65
85
|
end
|
66
|
-
|
86
|
+
end
|
87
|
+
value = res+rest.gsub(/\\(.)/, '\1').chomp
|
88
|
+
value = value[1..-2] unless value.to_s == ''
|
89
|
+
args = "[#{args.join(', ')}]"
|
90
|
+
[value, args]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.enabled?
|
94
|
+
@enabled
|
95
|
+
end
|
96
|
+
|
97
|
+
# Enable magic translations using the given backend
|
98
|
+
#
|
99
|
+
# Supported backends:
|
100
|
+
#
|
101
|
+
# +:i18n+:: Use I18n::Backend::GetText and I18n::GetText::Helpers
|
102
|
+
# from the 'i18n'
|
103
|
+
# +:gettext+:: Use GetText from 'gettext'
|
104
|
+
# +:fast_gettext+:: Use FastGettext::Translation from 'fast_gettext'
|
105
|
+
def self.enable(backend = :i18n)
|
106
|
+
case backend
|
107
|
+
when :i18n
|
108
|
+
require 'i18n'
|
109
|
+
require 'i18n/backend/gettext'
|
110
|
+
require 'i18n/gettext/helpers'
|
111
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Gettext)
|
112
|
+
EngineMethods.magic_translations_helpers = I18n::Gettext::Helpers
|
113
|
+
when :gettext
|
114
|
+
require 'gettext'
|
115
|
+
EngineMethods.magic_translations_helpers = GetText
|
116
|
+
when :fast_gettext
|
117
|
+
require 'fast_gettext'
|
118
|
+
EngineMethods.magic_translations_helpers = FastGettext::Translation
|
119
|
+
else
|
120
|
+
@enabled = false
|
121
|
+
raise ArgumentError, "Backend #{backend.to_s} is not available in Haml::MagicTranslations"
|
122
|
+
end
|
123
|
+
@enabled = true
|
124
|
+
end
|
125
|
+
|
126
|
+
# Disable magic translations
|
127
|
+
def self.disable
|
128
|
+
EngineMethods.magic_translations_helpers = nil
|
129
|
+
@enabled = false
|
130
|
+
end
|
131
|
+
|
132
|
+
module TemplateMethods # :nodoc:all
|
133
|
+
# backward compatibility with versions < 0.3
|
134
|
+
def enable_magic_translations(backend = :i18n)
|
135
|
+
Haml::MagicTranslations.enable backend
|
67
136
|
end
|
68
137
|
end
|
69
|
-
|
70
|
-
module EngineMethods
|
138
|
+
|
139
|
+
module EngineMethods # :nodoc:all
|
140
|
+
class << self
|
141
|
+
attr_accessor :magic_translations_helpers
|
142
|
+
end
|
143
|
+
|
144
|
+
def magic_translations?
|
145
|
+
return self.options[:magic_translations] unless self.options[:magic_translations].nil?
|
146
|
+
|
147
|
+
Haml::MagicTranslations.enabled?
|
148
|
+
end
|
149
|
+
|
71
150
|
# Overriden function that parses Haml tags. Injects gettext call for all plain
|
72
151
|
# text lines.
|
73
152
|
def parse_tag(line)
|
74
153
|
tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
75
154
|
nuke_inner_whitespace, action, value, last_line = super(line)
|
76
|
-
|
77
|
-
magic_translations
|
78
|
-
|
79
|
-
|
80
|
-
if magic_translations
|
81
|
-
unless action && action != '!' || action == '!' && value[0] == '=' || value.empty?
|
82
|
-
value, interpolation_arguments = prepare_i18n_interpolation(value)
|
155
|
+
|
156
|
+
if magic_translations? && !value.empty?
|
157
|
+
unless action && action == '=' || action == '!' && value[0] == ?= || action == '&' && value[0] == ?=
|
158
|
+
value, interpolation_arguments = Haml::MagicTranslations.prepare_i18n_interpolation(value)
|
83
159
|
value = "\#{_('#{value.gsub(/'/, "\\\\'")}') % #{interpolation_arguments}\}\n"
|
84
160
|
end
|
85
161
|
end
|
86
162
|
[tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
87
163
|
nuke_inner_whitespace, action, value, last_line]
|
88
164
|
end
|
89
|
-
|
90
|
-
# Magical translations will be also used for plain text.
|
91
|
-
def push_plain(text, options = {})
|
92
|
-
if block_opened?
|
93
|
-
raise SyntaxError.new("Illegal nesting: nesting within plain text is illegal.", @next_line.index)
|
94
|
-
end
|
95
165
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
value, interpolation_arguments = prepare_i18n_interpolation(text,
|
101
|
-
:escape_html => options[:escape_html])
|
166
|
+
# Magical translations will be also used for plain text.
|
167
|
+
def plain(text, escape_html = nil)
|
168
|
+
if magic_translations?
|
169
|
+
value, interpolation_arguments = Haml::MagicTranslations.prepare_i18n_interpolation(text, escape_html)
|
102
170
|
value = "_('#{value.gsub(/'/, "\\\\'")}') % #{interpolation_arguments}\n"
|
103
|
-
|
171
|
+
script(value, !:escape_html)
|
104
172
|
else
|
105
|
-
|
106
|
-
options[:escape_html] = self.options[:escape_html] if options[:escape_html].nil?
|
107
|
-
push_script(
|
108
|
-
unescape_interpolation(text, :escape_html => options[:escape_html]),
|
109
|
-
:escape_html => false)
|
110
|
-
else
|
111
|
-
push_text text
|
112
|
-
end
|
173
|
+
super
|
113
174
|
end
|
114
175
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
rest = Haml::Shared.handle_interpolation '"' + str + '"' do |scan|
|
140
|
-
escapes = (scan[2].size - 1) / 2
|
141
|
-
res << scan.matched[0...-3 - escapes]
|
142
|
-
if escapes % 2 == 1
|
143
|
-
res << '#{'
|
144
|
-
else
|
145
|
-
content = eval('"' + balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
|
146
|
-
content = "Haml::Helpers.html_escape(#{content.to_s})" if opts[:escape_html]
|
147
|
-
args << content
|
148
|
-
res << '%s'
|
149
|
-
end
|
176
|
+
|
177
|
+
def compile_filter
|
178
|
+
super unless magic_translations?
|
179
|
+
|
180
|
+
case @node.value[:name]
|
181
|
+
when 'markdown'
|
182
|
+
@node.value[:text] = "\#{_(<<-'END_OF_TRANSLATABLE_MARKDOWN'.rstrip
|
183
|
+
#{@node.value[:text].rstrip.gsub(/\n/, '\n')}
|
184
|
+
END_OF_TRANSLATABLE_MARKDOWN
|
185
|
+
)}"
|
186
|
+
when 'javascript'
|
187
|
+
@node.value[:text].gsub!(/_\(('(([^']|\\')+)'|"(([^"]|\\")+)")\)/) do |m|
|
188
|
+
to_parse = $1[1..-2].gsub(/"/, '\"')
|
189
|
+
parsed_string = JSON.parse("[\"#{to_parse}\"]")[0]
|
190
|
+
parsed_string.gsub!(/'/, "\\\\'")
|
191
|
+
"\#{_('#{parsed_string}').to_json}"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
super
|
195
|
+
end
|
196
|
+
|
197
|
+
def compile_root
|
198
|
+
if magic_translations?
|
199
|
+
@precompiled << "extend #{EngineMethods.magic_translations_helpers};"
|
150
200
|
end
|
151
|
-
|
152
|
-
value = value[1..-2] unless value.to_s == ''
|
153
|
-
args = "[#{args.join(', ')}]"
|
154
|
-
[value, args]
|
201
|
+
super
|
155
202
|
end
|
156
203
|
end
|
157
204
|
end
|