i18n-translators-tools 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +44 -7
- data/bin/i18n-translate +34 -10
- data/i18n-translators-tools.gemspec +12 -5
- data/lib/i18n/backend/translate.rb +3 -1
- data/lib/i18n/processor.rb +32 -9
- data/lib/i18n/translate.rb +12 -1
- data/test/backend.rb +4 -0
- data/test/locale/src/default.yml +2 -0
- metadata +15 -8
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
I18n translation and locales management utility
|
2
2
|
===============================================
|
3
3
|
|
4
|
-
This package brings you useful utility which can help you to handle
|
5
|
-
and translations in your Ruby projects.
|
4
|
+
This package brings you useful utility and library which can help you to handle
|
5
|
+
locale files and translations in your Ruby projects.
|
6
6
|
|
7
7
|
|
8
8
|
Interesting features
|
@@ -11,7 +11,7 @@ Interesting features
|
|
11
11
|
* no database required
|
12
12
|
* merging and changes propagation (adding, removing and changed default text)
|
13
13
|
keeping default file untouched
|
14
|
-
* creating new locale file based default file
|
14
|
+
* creating new locale file based on default file
|
15
15
|
* converting from one format to another (yml <=> rb <=> po <=> ts <=> properties)
|
16
16
|
* statistics
|
17
17
|
* built-in simple console translator
|
@@ -58,6 +58,35 @@ WARNING
|
|
58
58
|
put all your rules to separate file and use exclude (repeatable) argument
|
59
59
|
or create configuration file for your project in locales directory including
|
60
60
|
exclude array.
|
61
|
+
* **in your set of keys in leaf can't be ALL keys reserved words**
|
62
|
+
this is ok:
|
63
|
+
|
64
|
+
en:
|
65
|
+
my:
|
66
|
+
key:
|
67
|
+
message: "some message"
|
68
|
+
reference: "http://..."
|
69
|
+
|
70
|
+
but this is NOT
|
71
|
+
|
72
|
+
en:
|
73
|
+
my:
|
74
|
+
key:
|
75
|
+
reference: "http://..."
|
76
|
+
|
77
|
+
**Reserved keywords are: **
|
78
|
+
* comment
|
79
|
+
* default
|
80
|
+
* extracted_comment
|
81
|
+
* file
|
82
|
+
* flag
|
83
|
+
* fuzzy
|
84
|
+
* line
|
85
|
+
* old
|
86
|
+
* old_default
|
87
|
+
* reference
|
88
|
+
* t
|
89
|
+
* translation
|
61
90
|
* **po files are supported only partialy.** If you convert from yaml or ruby to
|
62
91
|
po and back you don't have to care even if you are using pluralization.
|
63
92
|
If you are converting from po origin files then you can lose header of the
|
@@ -105,8 +134,7 @@ can native speakers put their polished english. I think it is good thing
|
|
105
134
|
to put all default strings into separate file(s). If you need to change
|
106
135
|
some text you don't have to touch source code.
|
107
136
|
|
108
|
-
Default files
|
109
|
-
is only for locales.
|
137
|
+
_(Default files can be now in enhanced format.)_
|
110
138
|
|
111
139
|
So in your application you should do something like this:
|
112
140
|
|
@@ -136,6 +164,11 @@ untranslated strings this can fix the problem.
|
|
136
164
|
Examples
|
137
165
|
--------
|
138
166
|
|
167
|
+
**Simple conversion from one file format to another:**
|
168
|
+
|
169
|
+
$> i18n-translate cze.yml cze.po
|
170
|
+
$> i18n-translate cze.po cze.properties
|
171
|
+
|
139
172
|
Suppose we have our locales in 'locale/' directory without sub-directories and
|
140
173
|
default values are inside 'locale/default.yml' file. And we have two files
|
141
174
|
with locales 'locale/de_DE.yml', 'locale/cs_CZ.yml' and 'locale/extra/cs_CZ.yml'
|
@@ -237,6 +270,10 @@ New format looks like:
|
|
237
270
|
old_default: "old default string"
|
238
271
|
default: "new default string"
|
239
272
|
comment: "translator's comments"
|
273
|
+
extracted_comment: "po extracted comment"
|
274
|
+
reference: "po's reference"
|
275
|
+
file: "file parsed from reference"
|
276
|
+
line: "line parsed from po reference"
|
240
277
|
translation: "translation itself"
|
241
278
|
flag: "one of (ok || incomplete || changed || untranslated)"
|
242
279
|
fuzzy: true # exists only where flag != ok (nice to have when you want
|
@@ -258,8 +295,8 @@ Pluralized variant should look like:
|
|
258
295
|
|
259
296
|
As you can see the old format is string and the new format is hash.
|
260
297
|
If you use lambdas and procs objects, you should save them in separate
|
261
|
-
file(s) because i18n-translate utility can't
|
262
|
-
can.
|
298
|
+
file(s) in different (sub)directory because i18n-translate utility can't
|
299
|
+
handle them but Translate backend can.
|
263
300
|
|
264
301
|
|
265
302
|
Configure file format
|
data/bin/i18n-translate
CHANGED
@@ -82,16 +82,6 @@ CONFIG FILE
|
|
82
82
|
end
|
83
83
|
|
84
84
|
|
85
|
-
COMMANDS = %w(list stat create merge convert strip translate)
|
86
|
-
command = ARGV.shift
|
87
|
-
|
88
|
-
unless COMMANDS.include?(command)
|
89
|
-
print_help()
|
90
|
-
exit
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
85
|
begin
|
96
86
|
require 'rubygems'
|
97
87
|
rescue
|
@@ -101,6 +91,40 @@ require 'i18n'
|
|
101
91
|
require 'i18n-translate'
|
102
92
|
|
103
93
|
|
94
|
+
# converts from one file format to another
|
95
|
+
def convert(src, trg)
|
96
|
+
fname = File.basename(src)
|
97
|
+
tfname = File.basename(trg)
|
98
|
+
lang, format = $1, $2 if fname =~ /(.*)\.([^\.]*)$/
|
99
|
+
raise "bad file name '#{src}'" unless lang and format
|
100
|
+
tlang, tformat = $1, $2 if fname =~ /(.*)\.([^\.]*)$/
|
101
|
+
raise "bad file name '#{src}'" unless tlang and tformat
|
102
|
+
|
103
|
+
dir = File.dirname(src)
|
104
|
+
opts = {:locale_dir => dir, :locale => lang, :format => format, :default => lang}
|
105
|
+
tr = I18n::Translate::Translate.new(lang, opts)
|
106
|
+
data = {tlang => tr.target}
|
107
|
+
I18n::Translate::Processor.write(trg, data, tr)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
COMMANDS = %w(list stat create merge convert strip translate)
|
112
|
+
command = ARGV.shift
|
113
|
+
|
114
|
+
unless COMMANDS.include?(command)
|
115
|
+
if (ARGV.size == 1) and File.exists?(command)
|
116
|
+
if File.exists?(ARGV[0])
|
117
|
+
puts "!!! convert fails: file #{ARGV[0]} exists"
|
118
|
+
exit
|
119
|
+
end
|
120
|
+
convert(command, ARGV[0])
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
print_help()
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
|
127
|
+
|
104
128
|
def process_locale(tr, command, opts)
|
105
129
|
options = opts.dup
|
106
130
|
options.delete(:quiet) if command == 'list'
|
@@ -13,7 +13,7 @@ spec = Gem::Specification.new do |s|
|
|
13
13
|
s.email = "pejuko@gmail.com"
|
14
14
|
s.authors = ["Petr Kovar"]
|
15
15
|
s.name = 'i18n-translators-tools'
|
16
|
-
s.version = '0.2.
|
16
|
+
s.version = '0.2.3'
|
17
17
|
s.date = Time.now.strftime("%Y-%m-%d")
|
18
18
|
s.add_dependency('i18n', '>= 0.4.1')
|
19
19
|
s.add_dependency('ya2yaml')
|
@@ -61,6 +61,12 @@ Changelog:
|
|
61
61
|
* fix: for default format autodetection works again
|
62
62
|
* merge can be more verbose
|
63
63
|
|
64
|
+
v0.2.3
|
65
|
+
* fix: hash_to_keys can work with enhanced format => default can be in
|
66
|
+
enchanced format
|
67
|
+
* i18n-translate <source file> <target file>
|
68
|
+
automaticlay perform convert action from one file to another
|
69
|
+
|
64
70
|
For more information read README.md and CHANGELOG.md
|
65
71
|
|
66
72
|
-----------------------------------------------------------------------------
|
@@ -70,10 +76,11 @@ http://github.com/pejuko/i18n-translators-tools
|
|
70
76
|
=============================================================================
|
71
77
|
EOF
|
72
78
|
s.description = <<EOF
|
73
|
-
This package brings you useful utility which can help you to handle
|
74
|
-
and translations in your Ruby projects. Offers also built-in simple
|
75
|
-
Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and
|
76
|
-
Read README.md file and run i18n-translate without parameters
|
79
|
+
This package brings you useful utility and library which can help you to handle
|
80
|
+
locale files and translations in your Ruby projects. Offers also built-in simple
|
81
|
+
console editor. Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and
|
82
|
+
Java Properties. Read README.md file and run i18n-translate without parameters
|
83
|
+
for more information.
|
77
84
|
EOF
|
78
85
|
end
|
79
86
|
|
@@ -21,9 +21,11 @@ module I18n
|
|
21
21
|
result = super(locale, key, options)
|
22
22
|
return nil if result.kind_of?(String) and result.empty?
|
23
23
|
return result unless result.kind_of?(Hash)
|
24
|
-
return nil unless result[:t] or result[:translation]
|
24
|
+
return nil unless result[:t] or result[:translation] or result[:default]
|
25
25
|
|
26
26
|
tr = result[:translation] || result[:t]
|
27
|
+
tr = result[:default] if tr.to_s.empty?
|
28
|
+
|
27
29
|
return nil if tr.to_s.empty?
|
28
30
|
|
29
31
|
values = options.except(*I18n::Backend::Base::RESERVED_KEYS)
|
data/lib/i18n/processor.rb
CHANGED
@@ -12,10 +12,12 @@ module I18n::Translate
|
|
12
12
|
attr_reader :processors
|
13
13
|
end
|
14
14
|
|
15
|
+
# append processor to the registry
|
15
16
|
def self.<<(processor)
|
16
17
|
@processors << processor
|
17
18
|
end
|
18
19
|
|
20
|
+
# find processor for fname and use it to read data
|
19
21
|
def self.read(fname, tr)
|
20
22
|
processor = find_processor(fname)
|
21
23
|
raise "Unknown file format" unless processor
|
@@ -23,6 +25,7 @@ module I18n::Translate
|
|
23
25
|
worker.read
|
24
26
|
end
|
25
27
|
|
28
|
+
# find processor for fname and use it to save data
|
26
29
|
def self.write(fname, data, tr)
|
27
30
|
processor = find_processor(fname)
|
28
31
|
raise "Unknown file format `#{fname}'" unless processor
|
@@ -30,6 +33,7 @@ module I18n::Translate
|
|
30
33
|
worker.write(data)
|
31
34
|
end
|
32
35
|
|
36
|
+
# find appropriate processor for given file name
|
33
37
|
def self.find_processor(fname)
|
34
38
|
@processors.each do |processor|
|
35
39
|
return processor if processor.can_handle?(fname)
|
@@ -37,6 +41,7 @@ module I18n::Translate
|
|
37
41
|
nil
|
38
42
|
end
|
39
43
|
|
44
|
+
# register formats from all known processors
|
40
45
|
def self.init(default='yml')
|
41
46
|
@processors.each do |processor|
|
42
47
|
processor.register(default)
|
@@ -44,15 +49,19 @@ module I18n::Translate
|
|
44
49
|
end
|
45
50
|
|
46
51
|
|
52
|
+
# this is abstract class for processors. processors should mainly implement
|
53
|
+
# protected methdos import and export
|
47
54
|
class Template
|
48
55
|
FORMAT = []
|
49
56
|
|
57
|
+
# register new processor
|
50
58
|
def self.inherited(processor)
|
51
59
|
Processor << processor
|
52
60
|
end
|
53
61
|
|
54
62
|
attr_reader :filename, :translate
|
55
63
|
|
64
|
+
# initialize new processor
|
56
65
|
def initialize(fname, tr)
|
57
66
|
@filename = fname
|
58
67
|
@translate = tr
|
@@ -60,6 +69,7 @@ module I18n::Translate
|
|
60
69
|
@lang = $1.to_s.strip
|
61
70
|
end
|
62
71
|
|
72
|
+
# register proessors's formats
|
63
73
|
def self.register(default='yml')
|
64
74
|
self::FORMAT.each do |format|
|
65
75
|
unless I18n::Translate::FORMATS.include?(format)
|
@@ -73,6 +83,7 @@ module I18n::Translate
|
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
86
|
+
# read file into hash
|
76
87
|
def read
|
77
88
|
data = File.open(@filename, mode("r")) do |f|
|
78
89
|
f.flock File::LOCK_SH
|
@@ -81,6 +92,7 @@ module I18n::Translate
|
|
81
92
|
import(data)
|
82
93
|
end
|
83
94
|
|
95
|
+
# write hash to file
|
84
96
|
def write(data)
|
85
97
|
File.open(@filename, mode("w")) do |f|
|
86
98
|
f.flock File::LOCK_EX
|
@@ -88,6 +100,7 @@ module I18n::Translate
|
|
88
100
|
end
|
89
101
|
end
|
90
102
|
|
103
|
+
# check if processor can handle this file
|
91
104
|
def self.can_handle?(fname)
|
92
105
|
fname =~ %r{\.([^\.]+)$}i
|
93
106
|
self::FORMAT.include?($1)
|
@@ -95,14 +108,17 @@ module I18n::Translate
|
|
95
108
|
|
96
109
|
protected
|
97
110
|
|
111
|
+
# converts raw data from file to hash
|
98
112
|
def import(data)
|
99
113
|
data
|
100
114
|
end
|
101
115
|
|
116
|
+
# converts hash to raw
|
102
117
|
def export(data)
|
103
118
|
data
|
104
119
|
end
|
105
120
|
|
121
|
+
# converts inspected string back into normal string
|
106
122
|
def uninspect(str)
|
107
123
|
return nil unless str
|
108
124
|
str.gsub(%r!\\([\\#"abefnrstvx]|u\d{4}|u\{[^\}]+\}|\d{1,3}|x\d{1,2}|cx|C-[a-zA-Z]|M-[a-zA-Z])!) do |m|
|
@@ -116,22 +132,29 @@ module I18n::Translate
|
|
116
132
|
end
|
117
133
|
end
|
118
134
|
|
119
|
-
# convert old
|
135
|
+
# convert old, t shorthand fields
|
120
136
|
def migrate(data)
|
121
137
|
keys = I18n::Translate.hash_to_keys(data, @translate.options[:separator])
|
122
138
|
keys.each do |key|
|
123
|
-
|
124
|
-
next unless
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
139
|
+
entry = I18n::Translate.find(key, data, @translate.options[:separator])
|
140
|
+
next unless I18n::Translate.is_enhanced?(entry)
|
141
|
+
%w(old t).each do |prop|
|
142
|
+
next unless entry[prop]
|
143
|
+
value = entry.delete(prop)
|
144
|
+
prop = case(prop)
|
145
|
+
when "old"
|
146
|
+
"old_default"
|
147
|
+
when "t"
|
148
|
+
"translation"
|
149
|
+
end
|
150
|
+
entry[prop] = value
|
151
|
+
end
|
152
|
+
I18n::Translate.set(key, entry, data, @translate.options[:separator])
|
131
153
|
end
|
132
154
|
data
|
133
155
|
end
|
134
156
|
|
157
|
+
# in ruby 1.9 it sets encoding for opening IOs
|
135
158
|
def mode(m)
|
136
159
|
mode = m.dup
|
137
160
|
mode << ":" << @translate.options[:encoding] if defined?(Encoding)
|
data/lib/i18n/translate.rb
CHANGED
@@ -53,6 +53,7 @@ module I18n::Translate
|
|
53
53
|
# function I18n::Translate::Processor.init will register known
|
54
54
|
# formats
|
55
55
|
FORMATS = %w() # the first one is preferred if :format => auto
|
56
|
+
RESERVED_WORDS = %w(comment extracted_comment reference file line default old_default fuzzy flag translation old t)
|
56
57
|
|
57
58
|
# read configuration file
|
58
59
|
# config format is ruby file which returns hash
|
@@ -60,12 +61,22 @@ module I18n::Translate
|
|
60
61
|
eval File.read(filename)
|
61
62
|
end
|
62
63
|
|
64
|
+
# checks if all keys are reserved keywords
|
65
|
+
def self.is_enhanced?(hash)
|
66
|
+
return false unless hash.kind_of?(Hash)
|
67
|
+
hash.keys.each do |key|
|
68
|
+
return false unless I18n::Translate::RESERVED_WORDS.include?(key)
|
69
|
+
end
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
63
73
|
# returns flat array of all keys e.g. ["system.message.ok", "system.message.error", ...]
|
64
74
|
def self.hash_to_keys(hash, separator=".", prefix="")
|
65
75
|
res = []
|
66
76
|
hash.keys.each do |key|
|
67
77
|
str = prefix.empty? ? key : "#{prefix}#{separator}#{key}"
|
68
|
-
|
78
|
+
enhanced = I18n::Translate.is_enhanced?(hash[key])
|
79
|
+
if hash[key].kind_of?(Hash) and (not enhanced)
|
69
80
|
str = hash_to_keys( hash[key], separator, str )
|
70
81
|
end
|
71
82
|
res << str
|
data/test/backend.rb
CHANGED
data/test/locale/src/default.yml
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-translators-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Petr Kovar
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-30 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -49,10 +49,11 @@ dependencies:
|
|
49
49
|
type: :runtime
|
50
50
|
version_requirements: *id002
|
51
51
|
description: |
|
52
|
-
This package brings you useful utility which can help you to handle
|
53
|
-
and translations in your Ruby projects. Offers also built-in simple
|
54
|
-
Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and
|
55
|
-
Read README.md file and run i18n-translate without parameters
|
52
|
+
This package brings you useful utility and library which can help you to handle
|
53
|
+
locale files and translations in your Ruby projects. Offers also built-in simple
|
54
|
+
console editor. Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and
|
55
|
+
Java Properties. Read README.md file and run i18n-translate without parameters
|
56
|
+
for more information.
|
56
57
|
|
57
58
|
email: pejuko@gmail.com
|
58
59
|
executables:
|
@@ -147,6 +148,12 @@ post_install_message: |
|
|
147
148
|
* fix: for default format autodetection works again
|
148
149
|
* merge can be more verbose
|
149
150
|
|
151
|
+
v0.2.3
|
152
|
+
* fix: hash_to_keys can work with enhanced format => default can be in
|
153
|
+
enchanced format
|
154
|
+
* i18n-translate <source file> <target file>
|
155
|
+
automaticlay perform convert action from one file to another
|
156
|
+
|
150
157
|
For more information read README.md and CHANGELOG.md
|
151
158
|
|
152
159
|
-----------------------------------------------------------------------------
|