l10nizer 0.0.10 → 1.1.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.
- checksums.yaml +7 -0
- data/bin/l10nizer +76 -18
- data/lib/l10nizer/keygen.rb +18 -11
- data/lib/l10nizer/locale_generator.rb +11 -0
- data/lib/l10nizer/namespacer.rb +7 -0
- data/lib/l10nizer/node.rb +24 -23
- data/lib/l10nizer/parser.rb +1 -1
- data/lib/l10nizer/processor.rb +7 -9
- data/lib/l10nizer/version.rb +6 -6
- data/lib/l10nizer.rb +2 -0
- metadata +91 -98
- data/README.md +0 -50
- data/Rakefile +0 -54
- data/test/samples/input.html.erb +0 -34
- data/test/samples/output.html.erb +0 -34
- data/test/test_key_generator.rb +0 -68
- data/test/test_processor.rb +0 -162
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9c42cf69ad08d236a007080c7098673a6c9b673b73c73e8005ebe91355f7fe4e
|
4
|
+
data.tar.gz: dfc6b968ca72ceb531856ce406f95abe860e200a9c469af1a35c22860b236a25
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bc3ae7a90574b9645e0dffacc7dce9f496641cda62ad549105b5b095c4f63e2ad178bdfd27a30d7e1b80fda038ccfa951fa9897600c46ccb50c046903ac12d58
|
7
|
+
data.tar.gz: '009657cc294a0e4f66c42bfcc56d3200835721ca5150281070125b384f02fc03d52e4bc85208d1d012a4082d0ca9444a8ccc859553e8f8d8fa0c5b7938dbfb4e'
|
data/bin/l10nizer
CHANGED
@@ -2,31 +2,89 @@
|
|
2
2
|
require "l10nizer"
|
3
3
|
require "yaml"
|
4
4
|
require "fileutils"
|
5
|
+
require "optparse"
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
executable = File.basename(__FILE__)
|
8
|
+
|
9
|
+
options = {
|
10
|
+
mode: :check,
|
11
|
+
path: "."
|
12
|
+
}
|
13
|
+
|
14
|
+
parser = OptionParser.new { |opts|
|
15
|
+
opts.banner = "Usage: #{executable} [options]"
|
16
|
+
opts.separator <<~STRING
|
17
|
+
|
18
|
+
#{executable} performs Automatic ex post facto localisation of Rails
|
19
|
+
templates.
|
20
|
+
|
21
|
+
By default, it will check for unlocalised text in templates, returning 0
|
22
|
+
if no such text is found, or returning 1 if it is found.
|
23
|
+
|
24
|
+
If the --extract option is passed, this text will be extracted from the
|
25
|
+
templates and deposited in a new file in config/locales/l10nized.yml.
|
26
|
+
|
27
|
+
STRING
|
28
|
+
|
29
|
+
opts.on(
|
30
|
+
"-e", "--extract",
|
31
|
+
"Replace strings with t() and write a locale file"
|
32
|
+
) do
|
33
|
+
options[:mode] = :extract
|
34
|
+
end
|
35
|
+
opts.on(
|
36
|
+
"-p", "--path", String,
|
37
|
+
"Path to Rails app (default: #{options[:path]})"
|
38
|
+
) do |str|
|
39
|
+
options[:path] = str
|
40
|
+
end
|
41
|
+
opts.on(
|
42
|
+
"-h", "--help",
|
43
|
+
"Display this help message and exit"
|
44
|
+
) do
|
45
|
+
puts opts
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.separator ""
|
50
|
+
}
|
51
|
+
|
52
|
+
parser.parse!
|
53
|
+
|
54
|
+
Dir.chdir(options[:path])
|
55
|
+
templates = Dir[File.join("app", "views", "**", "*.html.erb")]
|
56
|
+
raise "Can't find any templates in #{options[:path]}" unless templates.any?
|
9
57
|
|
10
58
|
keygen = L10nizer::KeyGenerator.new
|
59
|
+
namespacer = L10nizer::Namespacer.new
|
60
|
+
files_with_text = []
|
11
61
|
l10ns = {}
|
12
62
|
|
13
63
|
templates.each do |path|
|
14
|
-
keygen.namespace =
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
64
|
+
keygen.namespace = namespacer.call(path)
|
65
|
+
l10nizer = L10nizer::Processor.new(File.read(path), keygen)
|
66
|
+
next unless l10nizer.l10ns.any?
|
67
|
+
|
68
|
+
files_with_text << path
|
69
|
+
next unless options[:mode] == :extract
|
70
|
+
|
71
|
+
l10ns.merge! l10nizer.l10ns
|
72
|
+
File.write path, l10nizer.reformed
|
21
73
|
end
|
22
74
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
hash
|
27
|
-
}
|
75
|
+
if files_with_text.any?
|
76
|
+
warn "Found unlocalised text in the following files:",
|
77
|
+
*files_with_text
|
28
78
|
|
29
|
-
|
30
|
-
|
31
|
-
|
79
|
+
case options[:mode]
|
80
|
+
when :extract
|
81
|
+
tree = L10nizer::LocaleGenerator.new.call(l10ns)
|
82
|
+
path = File.join("config", "locales", "l10nized.yml")
|
83
|
+
FileUtils.mkdir_p File.dirname(path)
|
84
|
+
File.write path, YAML.dump(tree)
|
85
|
+
when :check
|
86
|
+
exit 1
|
87
|
+
end
|
88
|
+
else
|
89
|
+
warn "No unlocalised text found."
|
32
90
|
end
|
data/lib/l10nizer/keygen.rb
CHANGED
@@ -9,14 +9,21 @@ module L10nizer
|
|
9
9
|
def call(string)
|
10
10
|
provisional = [make_safe(namespace), make_safe(string)].compact * "."
|
11
11
|
|
12
|
-
until
|
13
|
-
provisional.
|
12
|
+
until distinct?(provisional, string)
|
13
|
+
match = provisional.match(/_(\d+)$/)
|
14
|
+
if match
|
15
|
+
provisional = provisional.sub(/\d+$/, match[1].to_i.succ.to_s)
|
16
|
+
else
|
17
|
+
provisional += "_1"
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
|
-
|
21
|
+
provisional
|
17
22
|
end
|
18
23
|
|
19
|
-
|
24
|
+
private
|
25
|
+
|
26
|
+
def distinct?(key, string)
|
20
27
|
if [nil, string].include?(@seen[key])
|
21
28
|
@seen[key] = string
|
22
29
|
true
|
@@ -27,13 +34,13 @@ module L10nizer
|
|
27
34
|
|
28
35
|
def make_safe(string)
|
29
36
|
return nil if string.nil?
|
30
|
-
safe = string
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
+
safe = string
|
38
|
+
.downcase
|
39
|
+
.gsub(/&[a-z0-9]{1,20};/, "") # entities
|
40
|
+
.gsub(/<[^>]*>/, "") # html
|
41
|
+
.gsub(/[^a-z0-9.]+/, "_") # non alphanumeric
|
42
|
+
.slice(0, 40) # limit length
|
43
|
+
.gsub(/^_|_$/, "") # leading/trailing _
|
37
44
|
safe = "unknown" if safe.empty?
|
38
45
|
safe
|
39
46
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module L10nizer
|
2
|
+
class LocaleGenerator
|
3
|
+
def call(l10ns, lang: "en")
|
4
|
+
lang_tree = l10ns.each_with_object({}) { |(key, value), hash|
|
5
|
+
parts = key.split(".")
|
6
|
+
parts[0..-2].inject(hash) { |h, k| h[k] ||= {} }[parts.last] = value
|
7
|
+
}
|
8
|
+
{lang => lang_tree}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/l10nizer/node.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module L10nizer
|
2
2
|
class NodeWrapperFactory
|
3
|
-
def self.wrap(node, keygen=nil)
|
3
|
+
def self.wrap(node, keygen = nil)
|
4
4
|
case node
|
5
5
|
when HtmlErb::Text
|
6
6
|
TextNode.new(node, keygen)
|
@@ -15,8 +15,8 @@ module L10nizer
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class BasicNode
|
18
|
-
def initialize(node, keygen=nil)
|
19
|
-
@node
|
18
|
+
def initialize(node, keygen = nil)
|
19
|
+
@node = node
|
20
20
|
@keygen = keygen
|
21
21
|
end
|
22
22
|
|
@@ -47,42 +47,43 @@ module L10nizer
|
|
47
47
|
vars, _ = vars_and_text
|
48
48
|
return super unless vars
|
49
49
|
|
50
|
-
params = ['"' + key + '"']
|
50
|
+
params = ['".' + key.split(".").last + '"']
|
51
51
|
vars.each_with_index do |v, i|
|
52
|
-
params << %{
|
52
|
+
params << %{#{variable_name(i)}: (#{v})}
|
53
53
|
end
|
54
54
|
|
55
55
|
%{<%= t(#{params * ", "}) %>}
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
private
|
59
|
+
|
59
60
|
def children
|
60
|
-
@node.children.map{ |e| NodeWrapperFactory.wrap(e) }
|
61
|
+
@node.children.map { |e| NodeWrapperFactory.wrap(e) }
|
61
62
|
end
|
62
63
|
|
63
64
|
def variable_name(index)
|
64
|
-
("a"
|
65
|
+
("a".."z").to_a[index]
|
65
66
|
end
|
66
67
|
|
68
|
+
# rubocop:disable Metrics/MethodLength
|
67
69
|
def vars_and_text
|
68
|
-
@vars_and_text ||= (
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
l10n << e.to_s
|
80
|
-
end
|
70
|
+
@vars_and_text ||= if children.all?(&:evaluated?) || children.none?(&:string?)
|
71
|
+
[]
|
72
|
+
else
|
73
|
+
l10n = ""
|
74
|
+
vars = []
|
75
|
+
children.each do |e|
|
76
|
+
if e.evaluated?
|
77
|
+
l10n << "%{#{variable_name(vars.length)}}"
|
78
|
+
vars << e.to_s
|
79
|
+
else
|
80
|
+
l10n << e.to_s
|
81
81
|
end
|
82
|
-
[vars, l10n]
|
83
82
|
end
|
84
|
-
|
83
|
+
[vars, l10n]
|
84
|
+
end
|
85
85
|
end
|
86
|
+
# rubocop:enable Metrics/MethodLength
|
86
87
|
|
87
88
|
def key
|
88
89
|
_, text = vars_and_text
|
data/lib/l10nizer/parser.rb
CHANGED
data/lib/l10nizer/processor.rb
CHANGED
@@ -9,21 +9,19 @@ module L10nizer
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def l10ns
|
12
|
-
processed.inject({}){ |hash, node| hash.merge(node.l10n) }
|
12
|
+
processed.inject({}) { |hash, node| hash.merge(node.l10n) }
|
13
13
|
end
|
14
14
|
|
15
15
|
def reformed
|
16
|
-
processed.map
|
16
|
+
processed.map(&:to_s).join
|
17
17
|
end
|
18
18
|
|
19
19
|
def processed
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
@processed
|
20
|
+
@processed ||=
|
21
|
+
HtmlErbParser.new
|
22
|
+
.parse(@html)
|
23
|
+
.elements
|
24
|
+
.map { |e| NodeWrapperFactory.wrap(e, @keygen) }
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
data/lib/l10nizer/version.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
module L10nizer
|
2
|
-
module VERSION
|
3
|
-
MAJOR =
|
4
|
-
MINOR =
|
5
|
-
TINY
|
1
|
+
module L10nizer # :nodoc:
|
2
|
+
module VERSION # :nodoc:
|
3
|
+
MAJOR = 1
|
4
|
+
MINOR = 1
|
5
|
+
TINY = 0
|
6
6
|
|
7
|
-
STRING = [MAJOR, MINOR, TINY].join(
|
7
|
+
STRING = [MAJOR, MINOR, TINY].join(".")
|
8
8
|
end
|
9
9
|
end
|
data/lib/l10nizer.rb
CHANGED
metadata
CHANGED
@@ -1,125 +1,118 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: l10nizer
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 10
|
10
|
-
version: 0.0.10
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Paul Battley
|
14
|
-
autorequire:
|
15
8
|
bindir: bin
|
16
9
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
10
|
+
date: 2025-03-04 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
22
13
|
name: treetop
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 19
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 2
|
33
|
-
- 6
|
34
|
-
version: 1.2.6
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.6'
|
35
19
|
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: polyglot
|
39
20
|
prerelease: false
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.6'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: polyglot
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.3.5
|
51
33
|
type: :runtime
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: thoughtbot-shoulda
|
55
34
|
prerelease: false
|
56
|
-
|
57
|
-
|
58
|
-
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.3.5
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: rake
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '13'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '13'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: standard
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
59
72
|
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
segments:
|
63
|
-
- 0
|
64
|
-
version: "0"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
65
75
|
type: :development
|
66
|
-
|
67
|
-
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
68
82
|
email: pbattley@gmail.com
|
69
|
-
executables:
|
83
|
+
executables:
|
70
84
|
- l10nizer
|
71
85
|
extensions: []
|
72
|
-
|
73
86
|
extra_rdoc_files: []
|
74
|
-
|
75
|
-
files:
|
76
|
-
- Rakefile
|
77
|
-
- README.md
|
87
|
+
files:
|
78
88
|
- bin/l10nizer
|
79
|
-
-
|
80
|
-
- test/test_processor.rb
|
81
|
-
- test/samples/input.html.erb
|
82
|
-
- test/samples/output.html.erb
|
83
|
-
- lib/l10nizer/version.rb
|
89
|
+
- lib/l10nizer.rb
|
84
90
|
- lib/l10nizer/grammar.treetop
|
85
|
-
- lib/l10nizer/node.rb
|
86
91
|
- lib/l10nizer/keygen.rb
|
87
|
-
- lib/l10nizer/
|
92
|
+
- lib/l10nizer/locale_generator.rb
|
93
|
+
- lib/l10nizer/namespacer.rb
|
94
|
+
- lib/l10nizer/node.rb
|
88
95
|
- lib/l10nizer/parser.rb
|
89
|
-
- lib/l10nizer.rb
|
90
|
-
|
91
|
-
homepage:
|
96
|
+
- lib/l10nizer/processor.rb
|
97
|
+
- lib/l10nizer/version.rb
|
92
98
|
licenses: []
|
93
|
-
|
94
|
-
post_install_message:
|
99
|
+
metadata: {}
|
95
100
|
rdoc_options: []
|
96
|
-
|
97
|
-
require_paths:
|
101
|
+
require_paths:
|
98
102
|
- lib
|
99
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
-
|
101
|
-
requirements:
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
102
105
|
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
version: "0"
|
108
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
-
none: false
|
110
|
-
requirements:
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
111
110
|
- - ">="
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
|
114
|
-
segments:
|
115
|
-
- 0
|
116
|
-
version: "0"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
117
113
|
requirements: []
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
specification_version: 3
|
123
|
-
summary: Automatically extract strings from ERB templates and replace with calls to t()
|
114
|
+
rubygems_version: 3.6.2
|
115
|
+
specification_version: 4
|
116
|
+
summary: Automatically extract strings from ERB templates and replace with calls to
|
117
|
+
t()
|
124
118
|
test_files: []
|
125
|
-
|
data/README.md
DELETED
@@ -1,50 +0,0 @@
|
|
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
DELETED
@@ -1,54 +0,0 @@
|
|
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/test/samples/input.html.erb
DELETED
@@ -1,34 +0,0 @@
|
|
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>
|
@@ -1,34 +0,0 @@
|
|
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>
|
data/test/test_key_generator.rb
DELETED
@@ -1,68 +0,0 @@
|
|
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 ' 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
|
data/test/test_processor.rb
DELETED
@@ -1,162 +0,0 @@
|
|
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
|