i18nliner 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|