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 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 locale files
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 have to be in the I18n simple format. The enhanced format
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 handle them but Translate backend
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
@@ -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.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 locale files
74
- and translations in your Ruby projects. Offers also built-in simple console editor.
75
- Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and Java Properties.
76
- Read README.md file and run i18n-translate without parameters for more information.
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)
@@ -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 and shorthand fields
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
- k, prop = $1, $2 if key =~ /(.*)\.([^\.]+)$/
124
- next unless prop or k
125
- next unless ["old", "t"].include?(prop)
126
- entry = I18n::Translate.find(k, data, @translate.options[:separator])
127
- value = entry.delete(prop)
128
- prop = (prop == "old") ? "old_default" : "translation"
129
- entry[prop] = value
130
- I18n::Translate.set(k, entry, data, @translate.options[:separator])
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)
@@ -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
- if hash[key].kind_of?(Hash)
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
@@ -51,5 +51,9 @@ module I18n::Test
51
51
  assert_equal( "tady je nějaký text", I18n.t("some text there") )
52
52
  end
53
53
 
54
+ def test_0120_enhanced_default_returns_default_if_translation_is_missing
55
+ assert_equal( "this is a key", I18n.t("test.enhanced") )
56
+ end
57
+
54
58
  end
55
59
  end
@@ -20,4 +20,6 @@ default:
20
20
  test:
21
21
  new_line: "In this text\nis a new line."
22
22
  quote: "This text contains \" -- one quote."
23
+ enhanced:
24
+ default: "this is a key"
23
25
  "some text there": "some text there"
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: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 2
10
- version: 0.2.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-28 00:00:00 +02:00
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 locale files
53
- and translations in your Ruby projects. Offers also built-in simple console editor.
54
- Supported formats are YAML, Ruby, Gettext po, QT Linguist TS and Java Properties.
55
- Read README.md file and run i18n-translate without parameters for more information.
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
  -----------------------------------------------------------------------------