i18nliner 0.0.2 → 0.0.3
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 +7 -27
- data/lib/i18nliner/base.rb +3 -1
- data/lib/i18nliner/call_helpers.rb +1 -1
- data/lib/i18nliner/commands/dump.rb +1 -1
- data/lib/i18nliner/commands/import.rb +30 -0
- data/lib/i18nliner/extensions/core.rb +1 -1
- data/lib/i18nliner/extractors/translation_hash.rb +25 -4
- data/spec/commands/check_spec.rb +1 -0
- data/spec/commands/dump_spec.rb +3 -1
- data/spec/extensions/core_spec.rb +8 -1
- data/spec/extractors/translation_hash_spec.rb +38 -0
- metadata +5 -3
data/README.md
CHANGED
@@ -2,16 +2,6 @@
|
|
2
2
|
|
3
3
|
[<img src="https://secure.travis-ci.org/jenseng/i18nliner.png" />](http://travis-ci.org/jenseng/i18nliner)
|
4
4
|
|
5
|
-
yay readme-driven development!
|
6
|
-
|
7
|
-
## TODO
|
8
|
-
|
9
|
-
* rake tasks
|
10
|
-
* diff
|
11
|
-
* import
|
12
|
-
|
13
|
-
====
|
14
|
-
|
15
5
|
I18nliner is I18n made simple.
|
16
6
|
|
17
7
|
No .yml files. Inline defaults. Optional keys. Inferred interpolation values.
|
@@ -87,8 +77,9 @@ translation? I18nliner makes keys optional, so you can just do this:
|
|
87
77
|
I18n.t "My Account"
|
88
78
|
```
|
89
79
|
|
90
|
-
I18nliner will create a
|
91
|
-
`:my_account`), so you don't have to.
|
80
|
+
I18nliner will create a unique key based on the translation (e.g.
|
81
|
+
`:my_account`), so you don't have to. See `I18nliner.inferred_key_format` for
|
82
|
+
more information.
|
92
83
|
|
93
84
|
This can actually be a **good thing**, because when the `en` changes, the key
|
94
85
|
changes, which means you know you need to get it retranslated (instead of
|
@@ -104,7 +95,7 @@ value. So this:
|
|
104
95
|
|
105
96
|
```erb
|
106
97
|
<p>
|
107
|
-
<%= t "Hello, %{user}. This request was a %{request_method}.",
|
98
|
+
<%= t "Hello, %{user}. This request was a %{request_method}.",
|
108
99
|
user: @user.name,
|
109
100
|
request_method: request.method
|
110
101
|
%>
|
@@ -237,7 +228,7 @@ before it hits ERB:
|
|
237
228
|
```
|
238
229
|
|
239
230
|
In other words, it will infer wrappers from your (balanced) markup and
|
240
|
-
|
231
|
+
`link_to` calls, and will create placeholders for any
|
241
232
|
other (inline) ERB expressions. ERB statements (e.g.
|
242
233
|
`<% if some_condition %>...`) and block expressions (e.g.
|
243
234
|
`<%= form_for @person do %>...`) are *not* supported within a block
|
@@ -305,27 +296,16 @@ Does an i18nliner:check, and then extracts all default translations from your
|
|
305
296
|
codebase, merges them with any other ones (from rails or pre-existing .yml
|
306
297
|
files), and outputs them to `config/locales/generated/en.yml`.
|
307
298
|
|
308
|
-
|
299
|
+
#### Dynamic Translations
|
309
300
|
|
310
301
|
Note that check and dump commands require all translation keys and
|
311
302
|
defaults to be literals. This is because it reads your code, it doesn't
|
312
303
|
run it. If you know what you are doing and want to pass in a variable or
|
313
|
-
other expression, you can use the `t!` (or `translate!`)
|
304
|
+
other expression, you can use the `t!` (or `translate!`) method. It works
|
314
305
|
the same as `t` at runtime, but signals to the extractor that it shouldn't
|
315
306
|
complain. You should only do this if you are sure that the specified
|
316
307
|
key/string is extracted elsewhere or already in your yml.
|
317
308
|
|
318
|
-
### i18nliner:diff
|
319
|
-
|
320
|
-
Does an i18nliner:dump and creates a diff from a previous one (path or git
|
321
|
-
commit hash). This is useful if you only want to see what has changed since a
|
322
|
-
previous release of your app.
|
323
|
-
|
324
|
-
### i18nliner:import
|
325
|
-
|
326
|
-
Imports a translated yml file. Ensures that all placeholders and wrappers are
|
327
|
-
present.
|
328
|
-
|
329
309
|
#### .i18nignore and more
|
330
310
|
|
331
311
|
By default, the check and dump tasks will look for inline translations in any
|
data/lib/i18nliner/base.rb
CHANGED
@@ -14,8 +14,9 @@ module I18nliner
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.manual_translations
|
17
|
+
I18n.t(:foo) # ensure backend is initialized
|
17
18
|
# TODO: support additional backends
|
18
|
-
I18n.backend.send(:translations)
|
19
|
+
I18n.backend.send(:translations)[I18n.default_locale]
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.look_up(key)
|
@@ -44,4 +45,5 @@ module I18nliner
|
|
44
45
|
setting :inferred_key_format, :underscored_crc32
|
45
46
|
setting :infer_interpolation_values, true
|
46
47
|
setting :base_path, "./"
|
48
|
+
setting :underscored_key_length, 50
|
47
49
|
end
|
@@ -16,7 +16,7 @@ module I18nliner
|
|
16
16
|
def run
|
17
17
|
FileUtils.mkdir_p File.dirname(yml_file)
|
18
18
|
File.open(yml_file, "w") do |file|
|
19
|
-
file.write({I18n.default_locale.to_s => @translations}.ya2yaml(:syck_compatible => true))
|
19
|
+
file.write({I18n.default_locale.to_s => @translations.expand_keys}.ya2yaml(:syck_compatible => true))
|
20
20
|
end
|
21
21
|
puts "Wrote default translations to #{yml_file}" unless @options[:silent]
|
22
22
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'i18nliner/commands/generic_command'
|
2
|
+
require 'i18nliner/extractors/translation_hash'
|
3
|
+
require 'active_support/core_ext/enumerable'
|
4
|
+
Dir[File.join(File.dirname(__FILE__), "../processors/*.rb")].each do |file|
|
5
|
+
require "i18nliner/processors/#{File.basename(file)}"
|
6
|
+
end
|
7
|
+
|
8
|
+
module I18nliner
|
9
|
+
module Commands
|
10
|
+
class Import < GenericCommand
|
11
|
+
attr_reader :translations, :errors
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def success?
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_summary
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
print_summary unless @options[:silent]
|
25
|
+
success?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -20,7 +20,7 @@ module I18nliner
|
|
20
20
|
|
21
21
|
# can't super this one yet :-/
|
22
22
|
def interpolate_hash_with_html_safety(string, values)
|
23
|
-
if string.html_safe? || values.values.any?(
|
23
|
+
if string.html_safe? || values.values.any?{ |v| v.is_a?(ActiveSupport::SafeBuffer) }
|
24
24
|
string = ERB::Util.h(string) unless string.html_safe?
|
25
25
|
values.each do |key, value|
|
26
26
|
values[key] = ERB::Util.h(value) unless value.html_safe?
|
@@ -4,14 +4,25 @@ module I18nliner
|
|
4
4
|
attr_accessor :line
|
5
5
|
|
6
6
|
def self.new(hash = {})
|
7
|
-
hash.is_a?(self) ? hash : super().replace(hash)
|
7
|
+
hash.is_a?(self) ? hash : super().replace(flatten(hash))
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
|
+
def self.flatten(hash, result = {}, prefix = "")
|
11
|
+
hash.each do |key, value|
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
flatten(value, result, "#{prefix}#{key}.")
|
14
|
+
else
|
15
|
+
result["#{prefix}#{key}"] = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
10
21
|
def initialize(*args)
|
11
22
|
super
|
12
23
|
@total_size = 0
|
13
24
|
end
|
14
|
-
|
25
|
+
|
15
26
|
def []=(key, value)
|
16
27
|
parts = key.split('.')
|
17
28
|
leaf = parts.pop
|
@@ -28,7 +39,7 @@ module I18nliner
|
|
28
39
|
hash = hash[part]
|
29
40
|
end
|
30
41
|
if hash[leaf]
|
31
|
-
if hash[leaf] !=
|
42
|
+
if hash[leaf] != value
|
32
43
|
if hash[leaf].is_a?(Hash)
|
33
44
|
raise KeyAsScopeError.new(@line, key)
|
34
45
|
else
|
@@ -40,6 +51,16 @@ module I18nliner
|
|
40
51
|
hash.store(leaf, value)
|
41
52
|
end
|
42
53
|
end
|
54
|
+
|
55
|
+
def expand_keys
|
56
|
+
result = {}
|
57
|
+
each do |key, value|
|
58
|
+
parts = key.split(".")
|
59
|
+
last = parts.pop
|
60
|
+
parts.inject(result){ |h, k2| h[k2] ||= {}}[last] = value
|
61
|
+
end
|
62
|
+
result
|
63
|
+
end
|
43
64
|
end
|
44
65
|
end
|
45
66
|
end
|
data/spec/commands/check_spec.rb
CHANGED
@@ -10,6 +10,7 @@ describe I18nliner::Commands::Check do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should find errors" do
|
13
|
+
allow(I18nliner).to receive(:manual_translations).and_return({})
|
13
14
|
checker = I18nliner::Commands::Check.new({:silent => true})
|
14
15
|
checker.check_files
|
15
16
|
checker.translations.values.should == ["welcome, %{name}", "Hello World", "*This* is a test, %{user}"]
|
data/spec/commands/dump_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'i18nliner/commands/dump'
|
3
|
+
require 'i18nliner/extractors/translation_hash'
|
3
4
|
require 'tmpdir'
|
4
5
|
|
5
6
|
describe I18nliner::Commands::Dump do
|
@@ -14,7 +15,8 @@ describe I18nliner::Commands::Dump do
|
|
14
15
|
end
|
15
16
|
|
16
17
|
it "should dump translations in utf8" do
|
17
|
-
|
18
|
+
translations = I18nliner::Extractors::TranslationHash.new('i18n' => "Iñtërnâtiônàlizætiøn")
|
19
|
+
dumper = I18nliner::Commands::Dump.new({:silent => true, :translations => translations})
|
18
20
|
dumper.run
|
19
21
|
File.read(dumper.yml_file).gsub(/\s+$/, '').should == <<-YML.strip_heredoc.strip
|
20
22
|
---
|
@@ -60,12 +60,19 @@ describe I18nliner::Extensions::Core do
|
|
60
60
|
result.should be_html_safe
|
61
61
|
end
|
62
62
|
|
63
|
-
it "should html-escape the string and other values if any value is html-safe" do
|
63
|
+
it "should html-escape the string and other values if any value is html-safe strings" do
|
64
64
|
markup = "<input>"
|
65
65
|
result = i18n.interpolate_hash("type %{input} & you get this: %{output}", :input => markup, :output => markup.html_safe)
|
66
66
|
result.should == "type <input> & you get this: <input>"
|
67
67
|
result.should be_html_safe
|
68
68
|
end
|
69
|
+
|
70
|
+
it "should not html-escape the string if the html-safe values are not strings" do
|
71
|
+
markup = "<input>"
|
72
|
+
result = i18n.interpolate_hash("my favorite number is %{number} & my favorite color is %{color}", :number => 1, :color => "red")
|
73
|
+
result.should == "my favorite number is 1 & my favorite color is red"
|
74
|
+
result.should_not be_html_safe
|
75
|
+
end
|
69
76
|
end
|
70
77
|
end
|
71
78
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'i18nliner/errors'
|
2
|
+
require 'i18nliner/extractors/translation_hash'
|
3
|
+
|
4
|
+
describe I18nliner::Extractors::TranslationHash do
|
5
|
+
|
6
|
+
describe "#[]=" do
|
7
|
+
let(:hash) { I18nliner::Extractors::TranslationHash.new }
|
8
|
+
|
9
|
+
it "should accept identical key/values" do
|
10
|
+
expect {
|
11
|
+
hash["foo"] = "Foo"
|
12
|
+
hash["foo"] = "Foo"
|
13
|
+
}.to_not raise_error
|
14
|
+
hash.should == {"foo" => "Foo"}
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should reject mismatched values" do
|
18
|
+
expect {
|
19
|
+
hash["foo"] = "Foo"
|
20
|
+
hash["foo"] = "Bar"
|
21
|
+
}.to raise_error(I18nliner::KeyInUseError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not let you use a key as a scope" do
|
25
|
+
expect {
|
26
|
+
hash["foo"] = "Foo"
|
27
|
+
hash["foo.bar"] = "Bar"
|
28
|
+
}.to raise_error(I18nliner::KeyAsScopeError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not let you use a scope as a key" do
|
32
|
+
expect {
|
33
|
+
hash["foo.bar"] = "Bar"
|
34
|
+
hash["foo"] = "Foo"
|
35
|
+
}.to raise_error(I18nliner::KeyAsScopeError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18nliner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-06-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -205,6 +205,7 @@ files:
|
|
205
205
|
- lib/i18nliner/commands/color_formatter.rb
|
206
206
|
- lib/i18nliner/commands/dump.rb
|
207
207
|
- lib/i18nliner/commands/generic_command.rb
|
208
|
+
- lib/i18nliner/commands/import.rb
|
208
209
|
- lib/i18nliner/errors.rb
|
209
210
|
- lib/i18nliner/erubis.rb
|
210
211
|
- lib/i18nliner/extensions/controller.rb
|
@@ -233,6 +234,7 @@ files:
|
|
233
234
|
- spec/extensions/view_spec.rb
|
234
235
|
- spec/extractors/ruby_extractor_spec.rb
|
235
236
|
- spec/extractors/translate_call_spec.rb
|
237
|
+
- spec/extractors/translation_hash_spec.rb
|
236
238
|
- spec/fixtures/app/models/invalid.rb
|
237
239
|
- spec/fixtures/app/models/valid.rb
|
238
240
|
- spec/pre_processors/erb_pre_processor_spec.rb
|
@@ -257,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
257
259
|
version: 1.3.5
|
258
260
|
requirements: []
|
259
261
|
rubyforge_project:
|
260
|
-
rubygems_version: 1.8.
|
262
|
+
rubygems_version: 1.8.23
|
261
263
|
signing_key:
|
262
264
|
specification_version: 3
|
263
265
|
summary: I18n made simple
|