l10nizer 0.0.9

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.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ L10nizer
2
+ ========
3
+
4
+ Automagic _ex post facto_ localisation for Rails templates.
5
+
6
+ What it does
7
+ ------------
8
+
9
+ Processes all your `html.erb` templates, extracts text, replaces it with `t()` calls, and generates a YAML file of localisations.
10
+
11
+ For example, given a file `app/views/things/show.html.erb` with this content:
12
+
13
+ <div class="thing">
14
+ <h1>Some heading</h1>
15
+ <p>This thing is called <%= h(@thing.name)</p>
16
+ </div>
17
+
18
+ l10nizer will change it to:
19
+
20
+ <div class="thing">
21
+ <h1><%= t("things.some_heading") %></h1>
22
+ <p><%= t("things.this_thing_is_called_a", :a => (h(@thing.name))) %></p>
23
+ </div>
24
+
25
+ and generate the following entries in `config/locales/l10nized.yml`:
26
+
27
+ things:
28
+ some_heading: Some heading
29
+ this_thing_is_called_a: This thing is called {{a}}
30
+
31
+ You can then use `l10nized.yml` as a basis for the localisation file for your current locale, e.g. `en_GB.yml`.
32
+
33
+ Usage
34
+ -----
35
+
36
+ From within a Rails application directory:
37
+
38
+ l10nizer
39
+
40
+ Specifying the application path explicitly:
41
+
42
+ l10nizer /path/to/my/rails/app
43
+
44
+ Limitations
45
+ -----------
46
+
47
+ * Perhaps ironically for a _localisation_ utility, l10nizer assumes that your templates are written in English or generally in ASCII, and ignores non-alphanumeric content when generating localisation keys. This could be fixed by modifying or replacing the L10nizer::KeyGenerator class.
48
+ * L10nizer takes no position on HTML entities or escaping. You __will__ need to review the changes it makes.
49
+ * Similarly, pluralisation is outside the scope of this application and will require attention.
50
+ * Strings that should be single entities but which contain HTML will be broken into multiple localisation strings.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require "rubygems"
2
+ require "rake/gempackagetask"
3
+ require "rake/testtask"
4
+ require "lib/l10nizer/version"
5
+
6
+ task :default => [:test]
7
+
8
+ Rake::TestTask.new("test") do |t|
9
+ t.libs << "test"
10
+ t.pattern = "test/**/test_*.rb"
11
+ t.verbose = true
12
+ end
13
+
14
+ task :default => :test
15
+
16
+ require "rake/testtask"
17
+ Rake::TestTask.new do |t|
18
+ t.libs << "test"
19
+ t.test_files = FileList["test/**/*_test.rb"]
20
+ t.verbose = true
21
+ end
22
+
23
+ spec = Gem::Specification.new do |s|
24
+ s.name = "l10nizer"
25
+ s.version = L10nizer::VERSION::STRING
26
+ s.summary = "Automatically extract strings from ERB templates and replace with calls to t()"
27
+ s.author = "Paul Battley"
28
+ s.email = "pbattley@gmail.com"
29
+
30
+ s.has_rdoc = false
31
+
32
+ s.files = %w(Rakefile README.md) + Dir.glob("{bin,test,lib}/**/*")
33
+ s.executables = FileList["bin/**"].map { |f| File.basename(f) }
34
+
35
+ s.require_paths = ["lib"]
36
+
37
+ s.add_dependency("treetop", ">= 1.2.6")
38
+ s.add_dependency("polyglot", ">= 0.2.5")
39
+
40
+ s.add_development_dependency("thoughtbot-shoulda")
41
+ end
42
+
43
+ Rake::GemPackageTask.new(spec) do |pkg|
44
+ pkg.gem_spec = spec
45
+
46
+ # Generate the gemspec file for github.
47
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
48
+ File.open(file, "w") {|f| f << spec.to_ruby }
49
+ end
50
+
51
+ desc 'Clear out generated packages'
52
+ task :clean => [:clobber_package] do
53
+ rm "#{spec.name}.gemspec"
54
+ end
data/bin/l10nizer ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ require "l10nizer"
3
+ require "yaml"
4
+ require "fileutils"
5
+
6
+ Dir.chdir(ARGV.first) if ARGV.first
7
+ templates = Dir["app/views/**/*.html.erb"]
8
+ raise "Can't find any templates in app/views." unless templates.any?
9
+
10
+ keygen = L10nizer::KeyGenerator.new
11
+ l10ns = {}
12
+
13
+ templates.each do |path|
14
+ keygen.namespace = path.split("/")[2]
15
+ source = File.read(path)
16
+ l10nizer = L10nizer::Processor.new(source, keygen)
17
+ l10ns.merge!(l10nizer.l10ns)
18
+ File.open(path, "w") do |f|
19
+ f << l10nizer.reformed
20
+ end
21
+ end
22
+
23
+ l10ns = l10ns.inject({}){ |hash, (key, value)|
24
+ parts = key.split(".")
25
+ parts[0 .. -2].inject(hash){ |h, k| h[k] ||= {} }[parts.last] = value
26
+ hash
27
+ }
28
+
29
+ FileUtils.mkdir_p("config/locales")
30
+ File.open("config/locales/l10nized.yml", "w") do |f|
31
+ f << l10ns.to_yaml
32
+ end
@@ -0,0 +1,53 @@
1
+ grammar HtmlErb
2
+ rule document
3
+ (html_comment / javascript / style / erb_control / whitespace / text / tag)* <Document>
4
+ end
5
+
6
+ rule html_comment
7
+ "<!--" ([^\-] / "-" [^\-] / "--" [^>])* "-->"
8
+ end
9
+
10
+ rule javascript
11
+ "<script" ([^<] / "<" [^/] / "</" [^s] / "</s" [^c] / "</sc" [^r] / "</scr" [^i] / "</scri" [^p] / "</scrip" [^t] / "</script" [^>"])* "</script>"
12
+ end
13
+
14
+ rule style
15
+ "<style" ([^<] / "<" [^/] / "</" [^s] / "</s" [^t] / "</st" [^y] / "</sty" [^l] / "</styl" [^e] / "</style" [^>"])* "</style>"
16
+ end
17
+
18
+ rule erb_control
19
+ "<%" [^=] ruby_code "%>"
20
+ end
21
+
22
+ rule tag
23
+ "<" (erb_control / erb_eval / [^>])+ ">"
24
+ end
25
+
26
+ rule whitespace
27
+ [\s]+
28
+ end
29
+
30
+ rule optional_whitespace
31
+ [\s]*
32
+ end
33
+
34
+ rule text
35
+ (optional_whitespace (erb_eval / inline_markup / word))+ <Text>
36
+ end
37
+
38
+ rule inline_markup
39
+ "<" "/"? ("em" / "strong") [^>]* ">"
40
+ end
41
+
42
+ rule word
43
+ [^<\s]+ <Word>
44
+ end
45
+
46
+ rule erb_eval
47
+ "<%=" ruby_code "%>" <Eval>
48
+ end
49
+
50
+ rule ruby_code
51
+ (("%" [^>]) / [^%])+
52
+ end
53
+ end
@@ -0,0 +1,41 @@
1
+ module L10nizer
2
+ class KeyGenerator
3
+ attr_accessor :namespace
4
+
5
+ def initialize
6
+ @seen = {}
7
+ end
8
+
9
+ def call(string)
10
+ provisional = [make_safe(namespace), make_safe(string)].compact * "."
11
+
12
+ until try(provisional, string)
13
+ provisional.sub!(/(?:_\d+)?$/){ |m| "_" + m.to_i.succ.to_s }
14
+ end
15
+
16
+ return provisional
17
+ end
18
+
19
+ def try(key, string)
20
+ if [nil, string].include?(@seen[key])
21
+ @seen[key] = string
22
+ true
23
+ else
24
+ false
25
+ end
26
+ end
27
+
28
+ def make_safe(string)
29
+ return nil if string.nil?
30
+ safe = string.
31
+ downcase.
32
+ gsub(/&[a-z0-9]{1,20};/, ""). # entities
33
+ gsub(/<[^>]*>/, ""). # html
34
+ gsub(/[^a-z0-9]+/, "_"). # non alphanumeric
35
+ slice(0, 40).
36
+ gsub(/^_|_$/, "") # leading/trailing _
37
+ safe = "unknown" if safe.empty?
38
+ safe
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,108 @@
1
+ module L10nizer
2
+ class NodeWrapperFactory
3
+ def self.wrap(node, keygen=nil)
4
+ case node
5
+ when HtmlErb::Text
6
+ TextNode.new(node, keygen)
7
+ when HtmlErb::Eval
8
+ EvalNode.new(node, keygen)
9
+ when HtmlErb::Word
10
+ WordNode.new(node)
11
+ else
12
+ BasicNode.new(node)
13
+ end
14
+ end
15
+ end
16
+
17
+ class BasicNode
18
+ def initialize(node, keygen=nil)
19
+ @node = node
20
+ @keygen = keygen
21
+ end
22
+
23
+ def l10n
24
+ {}
25
+ end
26
+
27
+ def to_s
28
+ @node.text_value
29
+ end
30
+
31
+ def evaluated?
32
+ false
33
+ end
34
+
35
+ def string?
36
+ false
37
+ end
38
+ end
39
+
40
+ class TextNode < BasicNode
41
+ def l10n
42
+ _, text = vars_and_text
43
+ text ? {key => text} : {}
44
+ end
45
+
46
+ def to_s
47
+ vars, _ = vars_and_text
48
+ return super unless vars
49
+
50
+ params = ['"' + key + '"']
51
+ vars.each_with_index do |v, i|
52
+ params << %{:#{variable_name(i)} => (#{v})}
53
+ end
54
+
55
+ %{<%= t(#{params * ", "}) %>}
56
+ end
57
+
58
+ private
59
+ def children
60
+ @node.children.map{ |e| NodeWrapperFactory.wrap(e) }
61
+ end
62
+
63
+ def variable_name(index)
64
+ ("a" .. "z").to_a[index]
65
+ end
66
+
67
+ def vars_and_text
68
+ @vars_and_text ||= (
69
+ if children.all?{ |c| c.evaluated? } || !children.any?{ |c| c.string? }
70
+ []
71
+ else
72
+ l10n = ""
73
+ vars = []
74
+ children.each do |e|
75
+ if e.evaluated?
76
+ l10n << "{{#{variable_name(vars.length)}}}"
77
+ vars << e.to_s
78
+ else
79
+ l10n << e.to_s
80
+ end
81
+ end
82
+ [vars, l10n]
83
+ end
84
+ )
85
+ end
86
+
87
+ def key
88
+ _, text = vars_and_text
89
+ @key ||= @keygen.call(text)
90
+ end
91
+ end
92
+
93
+ class EvalNode < BasicNode
94
+ def to_s
95
+ super[/\A<%=\s*(.*?)\s*%>\Z/, 1]
96
+ end
97
+
98
+ def evaluated?
99
+ true
100
+ end
101
+ end
102
+
103
+ class WordNode < BasicNode
104
+ def string?
105
+ true
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,20 @@
1
+ require "treetop"
2
+ require "polyglot"
3
+ require "l10nizer/grammar"
4
+
5
+ module HtmlErb
6
+ class Document < Treetop::Runtime::SyntaxNode
7
+ end
8
+
9
+ class Text < Treetop::Runtime::SyntaxNode
10
+ def children
11
+ elements.map{ |e| e.elements }.flatten
12
+ end
13
+ end
14
+
15
+ class Eval < Treetop::Runtime::SyntaxNode
16
+ end
17
+
18
+ class Word < Treetop::Runtime::SyntaxNode
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require "l10nizer/parser"
2
+ require "l10nizer/node"
3
+
4
+ module L10nizer
5
+ class Processor
6
+ def initialize(html, keygen)
7
+ @html = html
8
+ @keygen = keygen
9
+ end
10
+
11
+ def l10ns
12
+ processed.inject({}){ |hash, node| hash.merge(node.l10n) }
13
+ end
14
+
15
+ def reformed
16
+ processed.map{ |e| e.to_s }.join
17
+ end
18
+
19
+ def processed
20
+ unless @processed
21
+ kcode = $KCODE
22
+ $KCODE = "n"
23
+ @processed = HtmlErbParser.new.parse(@html).elements.map{ |e| NodeWrapperFactory.wrap(e, @keygen) }
24
+ $KCODE = kcode
25
+ end
26
+ @processed
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module L10nizer #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 9
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/l10nizer.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "l10nizer/processor"
2
+ require "l10nizer/keygen"
@@ -0,0 +1,34 @@
1
+ <li id="action_<%=h thing.whatsit.id %>" class="item underway">
2
+ <div class="wrap">
3
+ <div class="placeholder">
4
+ <%- if thing.whatsit.identity? -%>
5
+ <%- if thing.whatsit.identity.processed? -%>
6
+ <%= image_tag thing.whatsit.identity.url(:medium) %>
7
+ <%- else -%>
8
+ <%= t("general.processing_image") %>
9
+ <%- end -%>
10
+ <%- end -%>
11
+ </div>
12
+ <h3>
13
+ <% link_to(thing) do %>
14
+ <span><%=h thing.whatsit.name %></span><%=h thing.short_address %>
15
+ <% end %>
16
+ </h3>
17
+ </div>
18
+ <div class="details">
19
+ <div class="format">
20
+ <h4 class="obfuscate">Skills</h4>
21
+ <ul class="skills">
22
+ <% thing.whatsit.skills.each do |skill| %>
23
+ <li class="skill">
24
+ <%= skill_icon(skill, :small) %>
25
+ </li>
26
+ <% end %>
27
+ <li class="engagement">
28
+ <%= engagement_icon(4, :small) %>
29
+ </li>
30
+ </ul>
31
+ <%=h truncate(thing.whatsit.short_description, :length => 130) %>
32
+ </div>
33
+ </div>
34
+ </li>
@@ -0,0 +1,34 @@
1
+ <li id="action_<%=h thing.whatsit.id %>" class="item underway">
2
+ <div class="wrap">
3
+ <div class="placeholder">
4
+ <%- if thing.whatsit.identity? -%>
5
+ <%- if thing.whatsit.identity.processed? -%>
6
+ <%= image_tag thing.whatsit.identity.url(:medium) %>
7
+ <%- else -%>
8
+ <%= t("general.processing_image") %>
9
+ <%- end -%>
10
+ <%- end -%>
11
+ </div>
12
+ <h3>
13
+ <% link_to(thing) do %>
14
+ <span><%=h thing.whatsit.name %></span><%=h thing.short_address %>
15
+ <% end %>
16
+ </h3>
17
+ </div>
18
+ <div class="details">
19
+ <div class="format">
20
+ <h4 class="obfuscate"><%= t("skills") %></h4>
21
+ <ul class="skills">
22
+ <% thing.whatsit.skills.each do |skill| %>
23
+ <li class="skill">
24
+ <%= skill_icon(skill, :small) %>
25
+ </li>
26
+ <% end %>
27
+ <li class="engagement">
28
+ <%= engagement_icon(4, :small) %>
29
+ </li>
30
+ </ul>
31
+ <%=h truncate(thing.whatsit.short_description, :length => 130) %>
32
+ </div>
33
+ </div>
34
+ </li>
@@ -0,0 +1,68 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ require "test/unit"
4
+ require "l10nizer/keygen"
5
+ require "shoulda"
6
+
7
+ class KeyGeneratorTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @keygen = L10nizer::KeyGenerator.new
11
+ end
12
+
13
+ context "without namespacing" do
14
+ should "generate keys based on string" do
15
+ assert_equal "foo_bar_baz_a", @keygen.call("Foo bar baz {{a}}")
16
+ end
17
+
18
+ should "truncate exceptionally long keys" do
19
+ long = "blah_" * 20
20
+ short = "blah_blah_blah_blah_blah_blah_blah_blah"
21
+ assert_equal short, @keygen.call(long)
22
+ end
23
+
24
+ should "reuse key for same text" do
25
+ assert_equal @keygen.call("the same"), @keygen.call("the same")
26
+ end
27
+
28
+ should "prevent duplicate keys for different texts" do
29
+ assert_equal "a_thing", @keygen.call("a thing")
30
+ assert_equal "a_thing_1", @keygen.call("A thing")
31
+ assert_equal "a_thing_2", @keygen.call("A Thing")
32
+ end
33
+
34
+ should "generate non empty keys for punctuation" do
35
+ assert_not_equal "", @keygen.call("<>!@#%#.,")
36
+ end
37
+
38
+ should "skip entities in keys" do
39
+ assert_equal "foo_bar", @keygen.call("foo &apos; bar")
40
+ end
41
+
42
+ should "skip inline markup in keys" do
43
+ assert_equal "foo_bar", @keygen.call("foo <strong>bar</strong>")
44
+ end
45
+ end
46
+
47
+ context "with namespacing" do
48
+ setup do
49
+ @keygen.namespace = "ns1"
50
+ end
51
+
52
+ should "prepend namespace" do
53
+ assert_equal "ns1.foo", @keygen.call("Foo")
54
+ end
55
+
56
+ should "prevent duplicate keys for different texts" do
57
+ assert_equal "ns1.a_thing", @keygen.call("a thing")
58
+ assert_equal "ns1.a_thing_1", @keygen.call("A thing")
59
+ assert_equal "ns1.a_thing_2", @keygen.call("A Thing")
60
+ end
61
+
62
+ should "check duplication by namespace" do
63
+ assert_equal "ns1.a_thing", @keygen.call("a thing")
64
+ @keygen.namespace = "ns2"
65
+ assert_equal "ns2.a_thing", @keygen.call("A thing")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,162 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ require "test/unit"
4
+ require "l10nizer/processor"
5
+ require "shoulda"
6
+
7
+ class ProcessorTest < Test::Unit::TestCase
8
+
9
+ class DumbKeyGenerator
10
+ def call(string)
11
+ string.downcase.gsub(/[^a-z0-9]+/, "_").gsub(/^_|_$/, "")[0, 40]
12
+ end
13
+ end
14
+
15
+ context "when finding text" do
16
+ setup do
17
+ html = "just some text"
18
+ @l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
19
+ end
20
+
21
+ should "pass key to t()" do
22
+ expected = %{<%= t("just_some_text") %>}
23
+ assert_equal expected, @l10nizer.reformed
24
+ end
25
+
26
+ should "extract l10n strings" do
27
+ expected = {"just_some_text" => "just some text"}
28
+ assert_equal expected, @l10nizer.l10ns
29
+ end
30
+ end
31
+
32
+ context "when interpolating inline eval" do
33
+ setup do
34
+ html = "String <%= 27 %> with <%= 42 %>"
35
+ @l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
36
+ end
37
+
38
+ should "pass values to t()" do
39
+ expected = %{<%= t("string_a_with_b", :a => (27), :b => (42)) %>}
40
+ assert_equal expected, @l10nizer.reformed
41
+ end
42
+
43
+ should "extract l10n strings" do
44
+ expected = {"string_a_with_b" => "String {{a}} with {{b}}"}
45
+ assert_equal expected, @l10nizer.l10ns
46
+ end
47
+ end
48
+
49
+ context "when interpolating in multiple text strings" do
50
+ setup do
51
+ html = "<p>String <%= 27 %> with <%= 42 %></p><p>Another <%= 'x' %></p>"
52
+ @l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
53
+ end
54
+
55
+ should "pass values to t() reusing placeholder variables" do
56
+ expected = %{<p><%= t("string_a_with_b", :a => (27), :b => (42)) %></p><p><%= t("another_a", :a => ('x')) %></p>}
57
+ assert_equal expected, @l10nizer.reformed
58
+ end
59
+
60
+ should "extract l10n strings with placeholder variables" do
61
+ expected = {"string_a_with_b" => "String {{a}} with {{b}}", "another_a" => "Another {{a}}"}
62
+ assert_equal expected, @l10nizer.l10ns
63
+ end
64
+ end
65
+
66
+ should "not try to localise inline eval on its own" do
67
+ html = "<p><%= 27 %></p>"
68
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
69
+ assert_equal html, l10nizer.reformed
70
+ end
71
+
72
+ should "not try to localise an HTML comment" do
73
+ html = "<!-- <p><%= 27 %></p> --> <p> <!-- fooo --> </p>"
74
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
75
+ assert_equal html, l10nizer.reformed
76
+ end
77
+
78
+ should "not try to localise Javascript" do
79
+ html = "<script>var a = 3;</script> <script>var b = 'b';</script>"
80
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
81
+ assert_equal html, l10nizer.reformed
82
+ end
83
+
84
+ should "not try to localise inline styles" do
85
+ html = %{<style type="text/css">\nhtml.js .nojs {display: none; background:#fff!important;}\n</style>}
86
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
87
+ assert_equal html, l10nizer.reformed
88
+ end
89
+
90
+ should "not try to localise control inside a tag" do
91
+ html = %{<div class="user-skills block <% unless @user.skills.any? %>blank<% end %>">}
92
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
93
+ assert_equal html, l10nizer.reformed
94
+ end
95
+
96
+ context "when string contains inline markup" do
97
+ setup do
98
+ html = "<p>String with <strong>strong</strong> and <em>emphasised</em> text</p>"
99
+ @l10nizer = L10nizer::Processor.new(html, lambda{ "key" })
100
+ end
101
+
102
+ should "include that markup in text" do
103
+ expected = "String with <strong>strong</strong> and <em>emphasised</em> text"
104
+ assert_equal [expected], @l10nizer.l10ns.values
105
+ end
106
+
107
+ should "use only one localisation" do
108
+ expected = %{<p><%= t("key") %></p>}
109
+ assert_equal expected, @l10nizer.reformed
110
+ end
111
+ end
112
+
113
+ should "not consider <span> to be inline markup" do
114
+ html = %{foo <span>bar</span>}
115
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
116
+ assert_equal ["bar", "foo"], l10nizer.l10ns.values.sort
117
+ end
118
+
119
+ context "when parsing a sample document" do
120
+ setup do
121
+ @html = File.read(File.join(File.dirname(__FILE__), "samples", "input.html.erb"))
122
+ @expected = File.read(File.join(File.dirname(__FILE__), "samples", "output.html.erb"))
123
+ @l10nizer = L10nizer::Processor.new(@html, DumbKeyGenerator.new)
124
+ end
125
+
126
+ should "replace embedded text" do
127
+ actual = @l10nizer.reformed
128
+ #@expected.split(/\n/).zip(actual.split(/\n/)).each do |a, b|
129
+ # puts a, b unless a == b
130
+ #end
131
+ assert_equal @expected, actual
132
+ end
133
+
134
+ should "extract l10n strings" do
135
+ expected = {"skills" => "Skills"}
136
+ assert_equal expected, @l10nizer.l10ns
137
+ end
138
+ end
139
+
140
+ context "when $KCODE is 'UTF8'" do
141
+ setup do
142
+ @kcode = $KCODE
143
+ $KCODE = "UTF8"
144
+ end
145
+
146
+ teardown do
147
+ $KCODE = @kcode
148
+ end
149
+
150
+ should "parse multi-byte characters in strings" do
151
+ html = "<p>We’ve</p>"
152
+ l10nizer = L10nizer::Processor.new(html, DumbKeyGenerator.new)
153
+ assert_equal ["We’ve"], l10nizer.l10ns.values
154
+ end
155
+
156
+ should "not change $KCODE" do
157
+ l10nizer = L10nizer::Processor.new("", DumbKeyGenerator.new)
158
+ ignore = l10nizer.l10ns.values
159
+ assert_equal "UTF8", $KCODE
160
+ end
161
+ end
162
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: l10nizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.9
5
+ platform: ruby
6
+ authors:
7
+ - Paul Battley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-11 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: treetop
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.6
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: polyglot
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.5
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: thoughtbot-shoulda
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description:
46
+ email: pbattley@gmail.com
47
+ executables:
48
+ - l10nizer
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - Rakefile
55
+ - README.md
56
+ - bin/l10nizer
57
+ - test/samples/output.html.erb
58
+ - test/samples/input.html.erb
59
+ - test/test_key_generator.rb
60
+ - test/test_processor.rb
61
+ - lib/l10nizer/grammar.treetop
62
+ - lib/l10nizer/node.rb
63
+ - lib/l10nizer/parser.rb
64
+ - lib/l10nizer/processor.rb
65
+ - lib/l10nizer/keygen.rb
66
+ - lib/l10nizer/version.rb
67
+ - lib/l10nizer.rb
68
+ has_rdoc: true
69
+ homepage:
70
+ licenses: []
71
+
72
+ post_install_message:
73
+ rdoc_options: []
74
+
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ requirements: []
90
+
91
+ rubyforge_project:
92
+ rubygems_version: 1.3.5
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Automatically extract strings from ERB templates and replace with calls to t()
96
+ test_files: []
97
+