translation 1.17 → 1.22

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 12113892c41a14c8d164e01d9d9c2339a92436f8
4
- data.tar.gz: 403abefb4765377f59d145bb39fcfe477099cde3
2
+ SHA256:
3
+ metadata.gz: d45218917c9c922310e60826327cd83f9537b07ece00d855a36a83327e04f8ef
4
+ data.tar.gz: '009b17548c9e57c0a696d7910cd9a75a4e1329049406a45449e1a17382c94b72'
5
5
  SHA512:
6
- metadata.gz: c67cb77f2af77d56b26cfa9869196df3d62f478c3236a11cfdc5fa180d500c5795bbaab08a75920d5e88a1bd48c46a54d97e290dc48772b9ef1920d54582e7a6
7
- data.tar.gz: 196ada47e46d5bebdb347b314ca02f3035018341b18d9d57fa4ef39943705588546b1c96173af53ab0f543e1eb7bdaac4b8b788733806f371c6dc768405db555
6
+ metadata.gz: b438efc2955b5db716b73e8d4ae1044135c6296f57ea829b8f5bc3ba8734ec0f7ff73678842b8a88a0826cc3d8ade340a9dc18ea66e874690ce932b2f9f8c849
7
+ data.tar.gz: e46d5e83c77b4f3f7fc0b0496c753ca6634b39f0043992b77f83ce604163a4e5433730cff5b3c77318df698a98d936f99a9986fc7b643da1d87c6f009b9b1fbb
data/README.md CHANGED
@@ -35,16 +35,19 @@ Table of contents
35
35
  * [Add or Remove Language](#add-or-remove-language)
36
36
  * [Edit Language](#edit-language)
37
37
  * [Custom Languages](#custom-languages)
38
+ * [Fallbacks](#fallbacks)
38
39
  * [Change the current locale](#change-the-current-locale)
39
40
  * [Globally](#globally)
40
41
  * [Locally](#locally)
41
42
  * [Continuous Integration](#continuous-integration)
42
43
  * [Advanced Configuration Options](#advanced-configuration-options)
43
- * [Disable GetText](#disable-gettext)
44
+ * [Disable GetText or YAML](#disable-gettext-or-yaml)
44
45
  * [Ignored YAML keys](#ignored-yaml-keys)
45
- * [Source file formats (for GetText)](#source-file-formats-for-gettext)
46
46
  * [Custom localization key prefixes](#custom-localization-key-prefixes)
47
+ * [Source file formats (for GetText)](#source-file-formats-for-gettext)
48
+ * [Gems with GetText strings](#gems-with-gettext-strings)
47
49
  * [Paths where locales are stored (not recommended)](#paths-where-locales-are-stored-not-recommended)
50
+ * [GetText Object Class Monkey-Patching](#gettext-object-class-monkey-patching)
48
51
  * [Pure Ruby (without Rails)](#pure-ruby-without-rails)
49
52
  * [Testing](#testing)
50
53
  * [Contributing](#contributing)
@@ -202,24 +205,37 @@ Since you created a new project, the translation history and tags will unfortuna
202
205
 
203
206
  ### Custom Languages
204
207
 
205
- You may want to add a custom language that is derived from an existing language.
206
- It's useful if you want to change some translations for another instance of the
207
- application or for a specific customer.
208
+ Custom languages are convenient if you want to customize translations for a specific customer
209
+ or another instance of your application.
210
+
211
+ A custom language is always be derived from an [existing language](https://translation.io/docs/languages).
212
+ Its structure should be like:
213
+
214
+ ```ruby
215
+ "#{existing_language_code}-#{custom_text}"
216
+ ```
208
217
 
209
- The structure of a custom language is : existing language code + "-" + custom text.
218
+ where `custom_text` can only contain alphanumeric characters and `-`.
210
219
 
211
220
  Examples: `en-microsoft` or `fr-BE-custom`.
212
221
 
213
- Custom languages can be added like any other language and fallbacks work as expected.
214
- It means that if the `en-microsoft.some_key` is missing, then it will fallback to
215
- `en.some_key`. So you only need to translate keys that should be customized.
222
+ ### Fallbacks
223
+
224
+ Using [I18n (YAML)](#i18n-yaml) syntax, fallbacks will work as expected for any regional or custom
225
+ language. It means that if the `en-microsoft.example` key is missing,
226
+ then it will fallback to `en.example`. So you only need to translate keys that
227
+ are different from the main language.
228
+
229
+ Note that fallbacks are chained, so `fr-BE-custom` will fallback to `fr-BE` that will
230
+ fallback to `fr`.
216
231
 
217
- Note that fallback are chained, so `fr-be-custom` will fallback to `fr-be` that will
218
- itself fallback to `fr`.
232
+ Just make sure to add `config.i18n.fallbacks = true` to your `config/application.rb` file.
233
+ You can find more information about this
234
+ [here](https://guides.rubyonrails.org/configuring.html#configuring-i18n).
219
235
 
220
- Using GetText syntax, it will only fallback to the source language. So either you
221
- create a fallback mechanism by yourself or you avoid fallbacking
222
- by translating everything in Translation.io for that custom language.
236
+ Using [GetText](#gettext) syntax, it will only fallback to the source language.
237
+ So either you create a fallback mechanism by yourself or you avoid fallbacking
238
+ by translating everything in Translation.io for the regional or custom language.
223
239
 
224
240
  ## Change the current locale
225
241
 
@@ -235,9 +251,12 @@ class ApplicationController < ActionController::Base
235
251
  end
236
252
  ```
237
253
 
238
- It will automatically set the locale extracted from the user's browser `HTTP_ACCEPT_LANGUAGE` value, and keep it in the session between requests.
254
+ First time the user will connect, it will automatically set the locale extracted
255
+ from the user's browser `HTTP_ACCEPT_LANGUAGE` value, and keep it in the session between
256
+ requests.
239
257
 
240
- Update the current locale by redirecting the user to https://yourdomain.com?locale=fr or even https://yourdomain.com/fr if you scoped your routes like this:
258
+ Update the current locale by redirecting the user to https://yourdomain.com?locale=fr
259
+ or even https://yourdomain.com/fr if you scoped your routes like this:
241
260
 
242
261
  ```ruby
243
262
  scope "/:locale", :constraints => { locale: /[a-z]{2}/ } do
@@ -245,7 +264,8 @@ scope "/:locale", :constraints => { locale: /[a-z]{2}/ } do
245
264
  end
246
265
  ```
247
266
 
248
- The `set_locale` code is [here](https://github.com/translation/rails/blob/master/lib/translation_io/controller.rb#L3), feel free to override it with your own locale management.
267
+ The `set_locale` code is [here](https://github.com/translation/rails/blob/master/lib/translation_io/controller.rb#L3),
268
+ feel free to override it with your own locale management.
249
269
 
250
270
  Don't forget to define your available locales with [I18n.available_locales](http://guides.rubyonrails.org/i18n.html#setup-the-rails-application-for-internationalization).
251
271
 
@@ -265,9 +285,9 @@ More examples here: https://translation.io/blog/rails-i18n-with-locale
265
285
 
266
286
  ## Continuous Integration
267
287
 
268
- If you want fresh translations in your Continuous Integration workflow, you may find yourself calling `bundle exec rake translation:sync` very frequently.
288
+ If you want fresh translations in your Continuous Integration workflow, you may find yourself calling `bundle exec rake translation:sync` very frequently.
269
289
 
270
- Since this task can't be concurrently executed (we have a [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) strategy with a queue but it returns an error under heavy load), we implemented this threadsafe readonly task:
290
+ Since this task can't be concurrently executed (we have a [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) strategy with a queue but it returns an error under heavy load), we implemented this threadsafe readonly task:
271
291
 
272
292
  ```bash
273
293
  $ bundle exec rake translation:sync_readonly
@@ -281,12 +301,9 @@ The `TranslationIO.configure` block in `config/initializers/translation.rb` can
281
301
 
282
302
  Some options are described below but for an exhaustive list, please refer to [config.rb](https://github.com/translation/rails/blob/master/lib/translation_io/config.rb).
283
303
 
284
- ### Disable GetText
304
+ ### Disable GetText or YAML
285
305
 
286
- Sometimes, you only want to use YAML and don't want to be bothered by GetText at all.
287
- For these cases, you just have to add `disable_gettext` in the config file.
288
-
289
- For example:
306
+ If you want to only use YAML files and totally ignore GetText syntax, use:
290
307
 
291
308
  ```ruby
292
309
  TranslationIO.configure do |config|
@@ -296,6 +313,17 @@ TranslationIO.configure do |config|
296
313
  end
297
314
  ```
298
315
 
316
+ In contrast, if you only want to synchronize GetText files and leave the YAML
317
+ files unchanged, use:
318
+
319
+ ```ruby
320
+ TranslationIO.configure do |config|
321
+ ...
322
+ config.disable_yaml = true
323
+ ...
324
+ end
325
+ ```
326
+
299
327
  ### Ignored YAML keys
300
328
 
301
329
  Sometimes you would like to ignore some YAML keys coming from gems or so.
@@ -307,19 +335,45 @@ For example:
307
335
  TranslationIO.configure do |config|
308
336
  ...
309
337
  config.ignored_key_prefixes = [
310
- 'number.human.',
311
- 'admin.',
312
- 'errors.messages.',
313
- 'activerecord.errors.messages.',
314
- 'will_paginate.',
315
- 'helpers.page_entries_info.',
316
- 'views.pagination.',
317
- 'enumerize.visibility.'
338
+ 'number.human',
339
+ 'admin',
340
+ 'errors.messages',
341
+ 'activerecord.errors.messages',
342
+ 'will_paginate',
343
+ 'helpers.page_entries_info',
344
+ 'views.pagination',
345
+ 'enumerize.visibility'
318
346
  ]
319
347
  ...
320
348
  end
321
349
  ```
322
350
 
351
+ ### Custom localization key prefixes
352
+
353
+ Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans)
354
+ in the same place and that's bad. For example: date formats, number separators, default
355
+ currency or measure units, etc.
356
+
357
+ A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or
358
+ numbers to be displayed, right? Moreover, this special keys often contain special constructions (e.g.,
359
+ with percent signs or spaces) that he might break.
360
+
361
+ We think localization is part of the configuration of the app and it should not reach the translator UI at all.
362
+ That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.
363
+
364
+ We automatically treat [known localization keys](lib/translation_io/yaml_entry.rb), but if you would like
365
+ to add some more, use the `localization_key_prefixes` option.
366
+
367
+ For example:
368
+
369
+ ```ruby
370
+ TranslationIO.configure do |config|
371
+ ...
372
+ config.localization_key_prefixes = ['my_gem.date.formats']
373
+ ...
374
+ end
375
+ ```
376
+
323
377
  ### Source file formats (for GetText)
324
378
 
325
379
  If you are using GetText and you want to manage other file formats than:
@@ -342,28 +396,15 @@ TranslationIO.configure do |config|
342
396
  end
343
397
  ```
344
398
 
345
- ### Custom localization key prefixes
346
-
347
- Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans)
348
- in the same place and that's bad. For example: date formats, number separators, default
349
- currency or measure units, etc.
350
-
351
- A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or
352
- numbers to be displayed, right? Moreover, this special keys often contain special constructions (e.g.,
353
- with percent signs or spaces) that he might break.
354
-
355
- We think localization is part of the configuration of the app and it should not reach the translator UI at all.
356
- That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.
399
+ ### Gems with GetText strings
357
400
 
358
- We automatically treat [known localization keys](lib/translation_io/yaml_entry.rb), but if you would like
359
- to add some more, use the `localization_key_prefixes` option.
360
-
361
- For example:
401
+ Public gems usually don't make use of GetText strings, but if you created and localized your own gems
402
+ with the GetText syntax, you'll want to be able to synchronize them:
362
403
 
363
404
  ```ruby
364
405
  TranslationIO.configure do |config|
365
406
  ...
366
- config.localization_key_prefixes = ['my_gem.date.formats']
407
+ config.parsed_gems = ['your_gem_name']
367
408
  ...
368
409
  end
369
410
  ```
@@ -381,6 +422,30 @@ TranslationIO.configure do |config|
381
422
  end
382
423
  ```
383
424
 
425
+ ### GetText Object Class Monkey-Patching
426
+
427
+ GetText methods (`_('')`, etc.) are available everywhere in your application.
428
+ This is made by extending the global `Object` class.
429
+
430
+ You can disable the built-in `Object` monkey-patching if you
431
+ prefer a more granular approach:
432
+
433
+ ```ruby
434
+ TranslationIO.configure do |config|
435
+ ...
436
+ config.gettext_object_delegate = false
437
+ ...
438
+ end
439
+ ```
440
+
441
+ Don't forget to manually include the GetText methods where needed:
442
+
443
+ ```ruby
444
+ class Contact < ApplicationRecord
445
+ extend TranslationIO::Proxy
446
+ end
447
+ ```
448
+
384
449
  ## Pure Ruby (without Rails)
385
450
 
386
451
  This gem was created specifically for Rails, but you can also use it in a pure Ruby project by making some arrangements:
@@ -483,9 +548,16 @@ Credits: [@deecewan](https://github.com/deecewan)
483
548
 
484
549
  ### Others
485
550
 
486
- If you want to create a new client for your favorite language or framework, feel
487
- free to reach us on [contact@translation.io](mailto:contact@translation.io) and
488
- we'll assist you with the workflow logic and send you API docs.
551
+ If you want to create a new client for your favorite language or framework, please read our
552
+ [Create a Translation.io Library](https://translation.io/docs/create-library)
553
+ guide and use the special
554
+ [init](https://translation.io/docs/create-library#initialization) and
555
+ [sync](https://translation.io/docs/create-library#synchronization) endpoints.
556
+
557
+ You can also use the more [traditional API](https://translation.io/docs/api).
558
+
559
+ Feel free to contact us on [contact@translation.io](mailto:contact@translation.io) if
560
+ you need some help or if you want to share your library.
489
561
 
490
562
  ## License
491
563
 
@@ -5,8 +5,6 @@ module TranslationIO
5
5
  :nsgettext, :pgettext, :npgettext, :sgettext, :ngettext, :gettext,
6
6
  :np_, :ns_, :Nn_, :n_, :p_, :s_, :N_, :_
7
7
  ]
8
-
9
- TEXT_DOMAIN = 'app'
10
8
  end
11
9
 
12
10
  require 'translation_io/config'
@@ -33,7 +31,7 @@ module TranslationIO
33
31
 
34
32
  yield @config
35
33
 
36
- unless @config.disable_gettext
34
+ if !@config.disable_gettext
37
35
  require_gettext_dependencies
38
36
  add_missing_locales
39
37
  add_parser_for_erb_source_formats(@config.erb_source_formats)
@@ -45,13 +43,18 @@ module TranslationIO
45
43
  # include is private until Ruby 2.1
46
44
  Proxy.send(:include, GetText)
47
45
 
48
- Proxy.bindtextdomain(TEXT_DOMAIN, {
49
- :path => @config.locales_path,
50
- :output_charset => @config.charset
51
- })
46
+ @config.bound_text_domains.each do |bound_text_domain|
47
+ Proxy.bindtextdomain(bound_text_domain, {
48
+ :path => @config.locales_path,
49
+ :output_charset => @config.charset
50
+ })
51
+ end
52
+
53
+ Proxy.textdomain(@config.text_domain)
52
54
 
53
- Proxy.textdomain(TEXT_DOMAIN)
54
- Object.delegate *GETTEXT_METHODS, :to => Proxy
55
+ if @config.gettext_object_delegate
56
+ Object.delegate *GETTEXT_METHODS, :to => Proxy
57
+ end
55
58
  end
56
59
 
57
60
  @client = Client.new(@config.api_key, @config.endpoint)
@@ -9,8 +9,10 @@ module TranslationIO
9
9
  def run
10
10
  TranslationIO.info "Creating new MO files."
11
11
 
12
- Dir["#{@locales_path}/*/#{TEXT_DOMAIN}.po"].each do |po_path|
13
- mo_path = "#{File.dirname(po_path)}/LC_MESSAGES/app.mo"
12
+ text_domain = TranslationIO.config.text_domain
13
+
14
+ Dir["#{@locales_path}/*/#{text_domain}.po"].each do |po_path|
15
+ mo_path = "#{File.dirname(po_path)}/LC_MESSAGES/#{text_domain}.mo"
14
16
  TranslationIO.info mo_path, 2, 2
15
17
  FileUtils.mkdir_p(File.dirname(mo_path))
16
18
  GetText::Tools::MsgFmt.run(po_path, '-o', mo_path)
@@ -11,9 +11,11 @@ module TranslationIO
11
11
  def run
12
12
  TranslationIO.info "Saving new PO files."
13
13
 
14
+ text_domain = TranslationIO.config.text_domain
15
+
14
16
  @target_locales.each do |target_locale|
15
17
  if @parsed_response.has_key?("po_data_#{target_locale}")
16
- po_path = File.join(@locales_path, Locale::Tag.parse(target_locale).to_s, "#{TEXT_DOMAIN}.po")
18
+ po_path = File.join(@locales_path, Locale::Tag.parse(target_locale).to_s, "#{text_domain}.po")
17
19
  FileUtils.mkdir_p(File.dirname(po_path))
18
20
  TranslationIO.info po_path, 2, 2
19
21
 
@@ -19,7 +19,7 @@ module TranslationIO
19
19
 
20
20
  yaml_data = YAMLConversion.get_yaml_data_from_po_data(@parsed_response["yaml_po_data_#{target_locale}"], target_locale)
21
21
 
22
- top_comment = <<EOS
22
+ top_comment = <<-EOS
23
23
  # WARNING. THIS FILE WAS AUTO-GENERATED BY THE TRANSLATION GEM.
24
24
  # IF YOU UPDATE IT, YOUR CHANGES WILL BE LOST AT THE NEXT SYNC.
25
25
  #
@@ -24,6 +24,8 @@ module TranslationIO
24
24
  YamlEntry.localization?(key, value)
25
25
  end
26
26
 
27
+ params = {}
28
+
27
29
  @target_locales.each do |target_locale|
28
30
  yaml_path = File.join(@yaml_locales_path, "localization.#{target_locale}.yml")
29
31
 
@@ -35,32 +37,36 @@ module TranslationIO
35
37
 
36
38
  yaml_data = YAMLConversion.get_yaml_data_from_flat_translations(target_flat_special_translations)
37
39
 
38
- File.open(yaml_path, 'wb') do |file|
39
- file.write(self.class.top_comment)
40
- file.write(yaml_data)
41
- end
42
- end
40
+ params["yaml_data_#{target_locale}"] = yaml_data
43
41
 
44
- if not TranslationIO.config.test
45
- # Get YAML localization entries
46
- params = {}
47
- @target_locales.each do |target_locale|
48
- yaml_path = File.join(@yaml_locales_path, "localization.#{target_locale}.yml")
49
- params["yaml_data_#{target_locale}"] = File.read(yaml_path)
42
+ # To have a localization.xx.yml file during tests (without call to backend)
43
+ if TranslationIO.config.test
44
+ if YAML::load(yaml_data).present?
45
+ File.open(yaml_path, 'wb') do |file|
46
+ file.write(self.class.top_comment)
47
+ file.write(yaml_data)
48
+ end
49
+ end
50
50
  end
51
+ end
51
52
 
52
- TranslationIO.info "Collecting YAML localization entries from server."
53
+ TranslationIO.info "Collecting YAML localization entries from server."
53
54
 
55
+ # To have a localization.xx.yml file with call to backend
56
+ if !TranslationIO.config.test
54
57
  uri = URI("#{TranslationIO.client.endpoint}/projects/#{TranslationIO.client.api_key}/fill_yaml_localizations")
55
58
  parsed_response = BaseOperation.perform_request(uri, params)
56
59
 
57
- unless parsed_response.nil?
60
+ if !parsed_response.nil?
58
61
  @target_locales.each do |target_locale|
59
62
  yaml_path = File.join(@yaml_locales_path, "localization.#{target_locale}.yml")
63
+ yaml_data = parsed_response["yaml_data_#{target_locale}"]
60
64
 
61
- File.open(yaml_path, 'wb') do |file|
62
- file.write(self.class.top_comment)
63
- file.write(parsed_response["yaml_data_#{target_locale}"])
65
+ if yaml_data.present? && YAML::load(yaml_data).present?
66
+ File.open(yaml_path, 'wb') do |file|
67
+ file.write(self.class.top_comment)
68
+ file.write(yaml_data)
69
+ end
64
70
  end
65
71
  end
66
72
  end
@@ -68,7 +74,7 @@ module TranslationIO
68
74
  end
69
75
 
70
76
  def self.top_comment
71
- <<EOS
77
+ <<-EOS
72
78
  # THIS FILE CONTAINS LOCALIZATION KEYS : date and number formats, number precisions,
73
79
  # number separators and all non-textual values depending on the language.
74
80
  # These values must not reach the translator, so they are separated in this file.
@@ -19,7 +19,7 @@ module TranslationIO
19
19
  yaml_locales_path = config.yaml_locales_path
20
20
  yaml_file_paths = config.yaml_file_paths
21
21
 
22
- unless config.disable_gettext
22
+ if !config.disable_gettext
23
23
  BaseOperation::DumpMarkupGettextKeysStep.new(haml_source_files, :haml).run
24
24
  BaseOperation::DumpMarkupGettextKeysStep.new(slim_source_files, :slim).run
25
25
  end
@@ -27,27 +27,34 @@ module TranslationIO
27
27
  UpdatePotFileStep.new(pot_path, source_files + erb_source_files).run(params)
28
28
  UpdateAndCollectPoFilesStep.new(target_locales, pot_path, locales_path).run(params)
29
29
 
30
- create_yaml_pot_files_step = CreateYamlPoFilesStep.new(source_locale, target_locales, yaml_file_paths)
31
- create_yaml_pot_files_step.run(params)
30
+ if !config.disable_yaml
31
+ create_yaml_pot_files_step = CreateYamlPoFilesStep.new(source_locale, target_locales, yaml_file_paths)
32
+ create_yaml_pot_files_step.run(params)
32
33
 
33
- all_used_yaml_locales = create_yaml_pot_files_step.all_used_yaml_locales.to_a.map(&:to_s).sort
34
+ all_used_yaml_locales = create_yaml_pot_files_step.all_used_yaml_locales.to_a.map(&:to_s).sort
34
35
 
35
- warn_source_locale_unfound(source_locale, all_used_yaml_locales)
36
- warn_target_locale_unfound(target_locales, all_used_yaml_locales)
36
+ warn_source_locale_unfound(source_locale, all_used_yaml_locales)
37
+ warn_target_locale_unfound(target_locales, all_used_yaml_locales)
38
+ end
37
39
 
38
40
  TranslationIO.info "Sending data to server (it may take some time, please be patient. Sync will be faster)."
39
41
 
40
42
  uri = URI("#{client.endpoint}/projects/#{client.api_key}/init")
41
43
  parsed_response = BaseOperation.perform_request(uri, params)
42
44
 
43
- unless parsed_response.nil?
44
- BaseOperation::SaveNewPoFilesStep.new(target_locales, locales_path, parsed_response).run
45
- BaseOperation::SaveNewYamlFilesStep.new(target_locales, yaml_locales_path, parsed_response).run
46
- BaseOperation::SaveSpecialYamlFilesStep.new(source_locale, target_locales, yaml_locales_path, yaml_file_paths).run
47
- CleanupYamlFilesStep.new(source_locale, target_locales, yaml_file_paths, yaml_locales_path).run
48
- BaseOperation::CreateNewMoFilesStep.new(locales_path).run
45
+ if !parsed_response.nil?
46
+ if !config.disable_gettext
47
+ BaseOperation::SaveNewPoFilesStep.new(target_locales, locales_path, parsed_response).run
48
+ BaseOperation::CreateNewMoFilesStep.new(locales_path).run
49
+ end
50
+
51
+ if !config.disable_yaml
52
+ BaseOperation::SaveNewYamlFilesStep.new(target_locales, yaml_locales_path, parsed_response).run
53
+ BaseOperation::SaveSpecialYamlFilesStep.new(source_locale, target_locales, yaml_locales_path, yaml_file_paths).run
54
+ CleanupYamlFilesStep.new(source_locale, target_locales, yaml_file_paths, yaml_locales_path).run
55
+ info_yaml_directory_structure
56
+ end
49
57
 
50
- info_yaml_directory_structure
51
58
  info_project_url(parsed_response)
52
59
  end
53
60
 
@@ -55,7 +62,7 @@ module TranslationIO
55
62
  end
56
63
 
57
64
  def warn_source_locale_unfound(source_locale, all_used_yaml_locales)
58
- is_source_locale_unfound = !source_locale.in?(all_used_yaml_locales)
65
+ is_source_locale_unfound = !all_used_yaml_locales.include?(source_locale)
59
66
 
60
67
  if is_source_locale_unfound
61
68
  puts
@@ -81,7 +88,7 @@ module TranslationIO
81
88
  puts
82
89
  puts "----------"
83
90
  puts "Your `config.target_locales` are [#{target_locales.sort.join(', ')}]."
84
- puts "But we haven't found any YAML key for [#{target_locales_unfound.join(', ')}], is this normal?"
91
+ puts "But we haven't found any YAML key for [#{target_locales_unfound.sort.join(', ')}], is this normal?"
85
92
  puts "If not, check that you haven't misspelled the locale (ex. 'en-GB' instead of 'en')."
86
93
  puts "----------"
87
94
  puts "Do you want to continue? (y/N)"
@@ -13,22 +13,28 @@ module TranslationIO
13
13
  @yaml_file_paths.each do |locale_file_path|
14
14
  if locale_file_removable?(locale_file_path)
15
15
  if File.exist?(locale_file_path)
16
- content_hash = YAML::load(File.read(locale_file_path))
16
+ content_hash = YAML::load(File.read(locale_file_path)) || {}
17
+ source_content_hash = content_hash.select { |k| k.to_s == @source_locale.to_s }
17
18
 
18
- if content_hash
19
- new_content_hash = content_hash.keep_if { |k| k.to_s == @source_locale.to_s }
20
- else # loading an empty file returns false
21
- new_content_hash = {}
22
- end
23
-
24
- if new_content_hash.keys.any?
19
+ if source_content_hash.empty?
20
+ TranslationIO.info "Removing #{locale_file_path}", 2, 2
21
+ FileUtils.rm(locale_file_path)
22
+ elsif content_hash != source_content_hash # in case of mixed languages in source YAML file
25
23
  TranslationIO.info "Rewriting #{locale_file_path}", 2, 2
24
+
25
+ if TranslationIO.config.yaml_line_width
26
+ file_content = source_content_hash.to_yaml(:line_width => TranslationIO.config.yaml_line_width)
27
+ else
28
+ file_content = source_content_hash.to_yaml
29
+ end
30
+
31
+ file_content = file_content.gsub(/ $/, '') # remove trailing spaces
32
+
26
33
  File.open(locale_file_path, 'wb') do |file|
27
- file.write(new_content_hash.to_yaml)
34
+ file.write(file_content)
28
35
  end
29
36
  else
30
- TranslationIO.info "Removing #{locale_file_path}", 2, 2
31
- FileUtils.rm(locale_file_path)
37
+ # don't touch source
32
38
  end
33
39
  end
34
40
  end
@@ -11,8 +11,10 @@ module TranslationIO
11
11
  def run(params)
12
12
  TranslationIO.info "Updating PO files."
13
13
 
14
+ text_domain = TranslationIO.config.text_domain
15
+
14
16
  @target_locales.each do |target_locale|
15
- po_path = "#{@locales_path}/#{Locale::Tag.parse(target_locale).to_s}/#{TEXT_DOMAIN}.po"
17
+ po_path = "#{@locales_path}/#{Locale::Tag.parse(target_locale).to_s}/#{text_domain}.po"
16
18
  TranslationIO.info po_path, 2, 2
17
19
 
18
20
  if File.exist?(po_path)
@@ -22,15 +22,20 @@ module TranslationIO
22
22
  yaml_locales_path = config.yaml_locales_path
23
23
  yaml_file_paths = config.yaml_file_paths
24
24
 
25
- ApplyYamlSourceEditsStep.new(yaml_file_paths, source_locale).run(params)
25
+ if !config.disable_yaml
26
+ ApplyYamlSourceEditsStep.new(yaml_file_paths, source_locale).run(params)
27
+ end
26
28
 
27
- unless config.disable_gettext
29
+ if !config.disable_gettext
28
30
  BaseOperation::DumpMarkupGettextKeysStep.new(haml_source_files, :haml).run
29
31
  BaseOperation::DumpMarkupGettextKeysStep.new(slim_source_files, :slim).run
30
32
  end
31
33
 
32
34
  UpdatePotFileStep.new(pot_path, source_files + erb_source_files).run(params)
33
- CreateYamlPotFileStep.new(source_locale, yaml_file_paths).run(params)
35
+
36
+ if !config.disable_yaml
37
+ CreateYamlPotFileStep.new(source_locale, yaml_file_paths).run(params)
38
+ end
34
39
 
35
40
  if purge
36
41
  params['purge'] = 'true'
@@ -45,11 +50,16 @@ module TranslationIO
45
50
  uri = URI("#{client.endpoint}/projects/#{client.api_key}/sync")
46
51
  parsed_response = BaseOperation.perform_request(uri, params)
47
52
 
48
- unless parsed_response.nil?
49
- BaseOperation::SaveNewPoFilesStep.new(target_locales, locales_path, parsed_response).run
50
- BaseOperation::CreateNewMoFilesStep.new(locales_path).run
51
- BaseOperation::SaveNewYamlFilesStep.new(target_locales, yaml_locales_path, parsed_response).run
52
- BaseOperation::SaveSpecialYamlFilesStep.new(source_locale, target_locales, yaml_locales_path, yaml_file_paths).run
53
+ if !parsed_response.nil?
54
+ if !config.disable_gettext
55
+ BaseOperation::SaveNewPoFilesStep.new(target_locales, locales_path, parsed_response).run
56
+ BaseOperation::CreateNewMoFilesStep.new(locales_path).run
57
+ end
58
+
59
+ if !config.disable_yaml
60
+ BaseOperation::SaveNewYamlFilesStep.new(target_locales, yaml_locales_path, parsed_response).run
61
+ BaseOperation::SaveSpecialYamlFilesStep.new(source_locale, target_locales, yaml_locales_path, yaml_file_paths).run
62
+ end
53
63
 
54
64
  display_unused_segments(parsed_response, show_purgeable, purge)
55
65
 
@@ -12,66 +12,123 @@ module TranslationIO
12
12
 
13
13
  params.merge!({ :timestamp => metadata_timestamp })
14
14
  parsed_response = perform_source_edits_request(params)
15
+ source_edits = parsed_response['source_edits'].to_a
15
16
 
16
- unless parsed_response.nil?
17
- TranslationIO.info "Applying YAML source editions."
18
-
19
- parsed_response['source_edits'].each do |source_edit|
20
- inserted = false
21
-
22
- sort_by_project_locales_first(@yaml_file_paths).each do |file_path|
23
- yaml_hash = YAML::load(File.read(file_path))
24
- flat_yaml_hash = FlatHash.to_flat_hash(yaml_hash)
25
-
26
- flat_yaml_hash.each do |key, value|
27
- if key == "#{@source_locale}.#{source_edit['key']}"
28
- if value == source_edit['old_text']
29
- TranslationIO.info "#{source_edit['key']} | #{source_edit['old_text']} -> #{source_edit['new_text']}", 2, 2
30
-
31
- if locale_file_path_in_project?(file_path)
32
- flat_yaml_hash[key] = source_edit['new_text']
33
-
34
- File.open(file_path, 'w') do |f|
35
- f.write(FlatHash.to_hash(flat_yaml_hash).to_yaml)
36
- end
37
- else # override source text of gem
38
- yaml_path = File.join(TranslationIO.config.yaml_locales_path, "#{@source_locale}.yml")
39
-
40
- if File.exists?(yaml_path) # source yaml file
41
- yaml_hash = YAML::load(File.read(yaml_path))
42
- flat_yaml_hash = FlatHash.to_flat_hash(yaml_hash)
43
- else
44
- FileUtils::mkdir_p File.dirname(yaml_path)
45
- flat_yaml_hash = {}
46
- end
47
-
48
- flat_yaml_hash["#{@source_locale}.#{source_edit['key']}"] = source_edit['new_text']
49
-
50
- File.open(yaml_path, 'w') do |f|
51
- f.write(FlatHash.to_hash(flat_yaml_hash).to_yaml)
52
- end
53
- end
54
-
55
- inserted = true
56
- break
57
- else
58
- TranslationIO.info "#{source_edit['key']} | Ignored because translation was also updated in source YAML file", 2, 2
59
- end
60
- end
61
- end
17
+ TranslationIO.info "Applying YAML source editions."
18
+
19
+ source_edits.each do |source_edit|
20
+ applied = false
21
+
22
+ reload_or_reuse_yaml_sources
62
23
 
63
- break if inserted
24
+ @yaml_sources.each do |yaml_source|
25
+ yaml_file_path = yaml_source[:yaml_file_path]
26
+ yaml_flat_hash = yaml_source[:yaml_flat_hash]
27
+
28
+ yaml_flat_hash.each do |full_key, value|
29
+ if full_key == "#{@source_locale}.#{source_edit['key']}"
30
+ apply_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
31
+ applied = true
32
+ break
33
+ end
64
34
  end
35
+
36
+ break if applied
65
37
  end
66
38
  end
67
39
 
68
- File.open(TranslationIO.config.metadata_path, 'w') do |f|
69
- f.write({ 'timestamp' => Time.now.utc.to_i }.to_yaml)
70
- end
40
+ update_metadata_timestamp
71
41
  end
72
42
 
73
43
  private
74
44
 
45
+ def reload_or_reuse_yaml_sources
46
+ if yaml_sources_reload_needed?
47
+ @yaml_sources = sort_by_project_locales_first(@yaml_file_paths).collect do |yaml_file_path|
48
+ yaml_content = File.read(yaml_file_path)
49
+ yaml_hash = YAML::load(yaml_content)
50
+ yaml_flat_hash = FlatHash.to_flat_hash(yaml_hash)
51
+
52
+ {
53
+ :yaml_file_path => yaml_file_path,
54
+ :yaml_flat_hash => yaml_flat_hash
55
+ }
56
+ end
57
+ else
58
+ @yaml_sources
59
+ end
60
+ end
61
+
62
+ def yaml_sources_reload_needed?
63
+ @yaml_file_paths.sort != @yaml_sources.to_a.collect { |y_s| y_s[:yaml_file_path] }.sort
64
+ end
65
+
66
+ # Sort YAML file paths by project locales first, gem locales after
67
+ # (to replace "overridden" source first)
68
+ def sort_by_project_locales_first(yaml_file_paths)
69
+ yaml_file_paths.sort do |x, y|
70
+ a = locale_file_path_in_project?(x)
71
+ b = locale_file_path_in_project?(y)
72
+ (!a && b) ? 1 : ((a && !b) ? -1 : 0)
73
+ end
74
+ end
75
+
76
+ def apply_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
77
+ full_key = "#{@source_locale}.#{source_edit['key']}"
78
+
79
+ if yaml_flat_hash[full_key] == source_edit['old_text']
80
+ TranslationIO.info "#{source_edit['key']} | #{source_edit['old_text']} -> #{source_edit['new_text']}", 2, 2
81
+
82
+ if locale_file_path_in_project?(yaml_file_path)
83
+ apply_application_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
84
+ else # Override source text of gem inside the app
85
+ apply_gem_source_edit(source_edit)
86
+ end
87
+ else
88
+ TranslationIO.info "#{source_edit['key']} | #{source_edit['old_text']} -> #{source_edit['new_text']} | Ignored because translation was also updated in source YAML file", 2, 2
89
+ end
90
+ end
91
+
92
+ def apply_application_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
93
+ full_key = "#{@source_locale}.#{source_edit['key']}"
94
+ yaml_flat_hash[full_key] = source_edit['new_text']
95
+ file_content = to_hash_to_yaml(yaml_flat_hash)
96
+
97
+ File.open(yaml_file_path, 'w') do |f|
98
+ f.write(file_content)
99
+ end
100
+ end
101
+
102
+ def apply_gem_source_edit(source_edit)
103
+ # Source yaml file like config/locales/en.yml
104
+ yaml_file_path = File.expand_path(File.join(TranslationIO.config.yaml_locales_path, "#{@source_locale}.yml"))
105
+
106
+ if File.exists?(yaml_file_path)
107
+ # Complete existing hash if YAML file already exists
108
+ existing_yaml_source = @yaml_sources.detect { |y_s| normalize_path(y_s[:yaml_file_path]) == normalize_path(yaml_file_path) }
109
+ yaml_flat_hash = existing_yaml_source[:yaml_flat_hash]
110
+ else
111
+ # Create new hash if YAML file doesn't exist yet
112
+ FileUtils::mkdir_p File.dirname(yaml_file_path)
113
+ yaml_flat_hash = {}
114
+ @yaml_file_paths.push(yaml_file_path) # Application YAML are at the end of the list
115
+ end
116
+
117
+ apply_application_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
118
+ end
119
+
120
+ def to_hash_to_yaml(yaml_flat_hash)
121
+ yaml_hash = FlatHash.to_hash(yaml_flat_hash)
122
+
123
+ if TranslationIO.config.yaml_line_width
124
+ content = yaml_hash.to_yaml(:line_width => TranslationIO.config.yaml_line_width)
125
+ else
126
+ content = yaml_hash.to_yaml
127
+ end
128
+
129
+ content.gsub(/ $/, '') # remove trailing spaces
130
+ end
131
+
75
132
  def metadata_timestamp
76
133
  if File.exist?(TranslationIO.config.metadata_path)
77
134
  metadata_content = File.read(TranslationIO.config.metadata_path)
@@ -87,26 +144,26 @@ module TranslationIO
87
144
  end
88
145
  end
89
146
 
147
+ def update_metadata_timestamp
148
+ File.open(TranslationIO.config.metadata_path, 'w') do |f|
149
+ f.write({ 'timestamp' => Time.now.utc.to_i }.to_yaml)
150
+ end
151
+ end
152
+
90
153
  def perform_source_edits_request(params)
91
154
  uri = URI("#{TranslationIO.client.endpoint}/projects/#{TranslationIO.client.api_key}/source_edits")
92
155
  parsed_response = BaseOperation.perform_request(uri, params)
93
156
  end
94
157
 
95
- # Sort YAML file paths by project locales first, gem locales after
96
- # (to replace "overridden" source first)
97
- def sort_by_project_locales_first(yaml_file_paths)
98
- yaml_file_paths.sort do |x, y|
99
- a = locale_file_path_in_project?(x)
100
- b = locale_file_path_in_project?(y)
101
- (!a && b) ? 1 : ((a && !b) ? -1 : 0)
102
- end
103
- end
104
-
105
158
  def locale_file_path_in_project?(locale_file_path)
106
- TranslationIO.normalize_path(locale_file_path).start_with?(
107
- TranslationIO.normalize_path(TranslationIO.config.yaml_locales_path)
159
+ normalize_path(locale_file_path).start_with?(
160
+ normalize_path(TranslationIO.config.yaml_locales_path)
108
161
  )
109
162
  end
163
+
164
+ def normalize_path(path)
165
+ TranslationIO.normalize_path(path)
166
+ end
110
167
  end
111
168
  end
112
169
  end
@@ -1,24 +1,40 @@
1
1
  module TranslationIO
2
2
  class Config
3
- attr_accessor :api_key, :locales_path, :yaml_locales_path
4
- attr_accessor :source_locale, :target_locales
3
+ attr_accessor :api_key
4
+ attr_accessor :source_locale
5
+ attr_accessor :target_locales
5
6
  attr_accessor :endpoint
7
+ attr_accessor :metadata_path
6
8
  attr_accessor :verbose
7
9
  attr_accessor :test
8
10
 
11
+ attr_accessor :disable_yaml
12
+
13
+ attr_accessor :yaml_locales_path
9
14
  attr_accessor :ignored_key_prefixes
15
+ attr_accessor :localization_key_prefixes
16
+ attr_accessor :yaml_line_width
17
+ attr_accessor :yaml_remove_empty_keys
18
+
19
+ attr_accessor :disable_gettext
20
+
21
+ attr_accessor :gettext_object_delegate
22
+
23
+ attr_accessor :locales_path
24
+
10
25
  attr_accessor :ignored_source_paths
11
26
  attr_accessor :ignored_source_files
12
27
 
28
+ attr_accessor :parsed_gems
29
+
13
30
  attr_accessor :source_formats
14
31
  attr_accessor :erb_source_formats
15
32
  attr_accessor :haml_source_formats
16
33
  attr_accessor :slim_source_formats
17
34
 
18
- attr_accessor :localization_key_prefixes
19
- attr_accessor :disable_gettext
35
+ attr_accessor :text_domain
36
+ attr_accessor :bound_text_domains
20
37
  attr_accessor :charset
21
- attr_accessor :metadata_path
22
38
 
23
39
  attr_accessor :pot_msgid_bugs_address
24
40
  attr_accessor :pot_package_name
@@ -27,37 +43,84 @@ module TranslationIO
27
43
  attr_accessor :pot_copyright_year
28
44
 
29
45
  def initialize
30
- self.locales_path = File.join('config', 'locales', 'gettext')
31
- self.yaml_locales_path = File.join('config', 'locales')
32
- self.source_locale = :en
33
- self.target_locales = []
34
- self.endpoint = 'https://translation.io/api'
35
- self.verbose = 1
36
- self.test = false
37
-
38
- self.ignored_key_prefixes = []
39
- self.ignored_source_paths = ['vendor/', 'tmp/']
40
- self.ignored_source_files = [] # Files not parsed for GetText entries
41
-
42
- self.source_formats = ['rb', 'ruby', 'rabl']
43
- self.erb_source_formats = ['erb', 'inky']
44
- self.haml_source_formats = ['haml', 'mjmlhaml']
45
- self.slim_source_formats = ['slim', 'mjmlslim']
46
46
 
47
+ #######
48
+ # Global options
49
+ #######
50
+
51
+ self.api_key = ''
52
+ self.source_locale = :en
53
+ self.target_locales = []
54
+ self.endpoint = 'https://translation.io/api'
55
+ self.metadata_path = File.join('config', 'locales', '.translation_io')
56
+ self.verbose = 1
57
+ self.test = false
58
+
59
+ #######
60
+ # YAML options
61
+ #######
62
+
63
+ self.disable_yaml = false
64
+
65
+ # YAML directory
66
+ self.yaml_locales_path = File.join('config', 'locales')
67
+
68
+ # Ignored YAML key prefixes (like 'will_paginate.')
69
+ self.ignored_key_prefixes = []
70
+
71
+ # Cf. https://github.com/translation/rails#custom-localization-key-prefixes
47
72
  self.localization_key_prefixes = []
48
- self.disable_gettext = false
49
- self.charset = 'UTF-8'
50
- self.metadata_path = File.join('config', 'locales', '.translation_io')
51
-
52
- self.pot_msgid_bugs_address = 'contact@translation.io'
53
- self.pot_package_name = File.basename(Dir.pwd)
54
- self.pot_package_version = '1.0'
55
- self.pot_copyright_holder = File.basename(Dir.pwd)
56
- self.pot_copyright_year = Date.today.year
73
+
74
+ # Define max line width of generated YAML files:
75
+ # Can be nil (default behaviour of Ruby version), -1 (no wrapping) or positive integer (wrapping)
76
+ # Cf. https://github.com/translation/rails/issues/19
77
+ self.yaml_line_width = nil
78
+
79
+ # Remove empty keys from translated YAML files
80
+ # Cf. https://github.com/translation/rails/pull/37
81
+ self.yaml_remove_empty_keys = false
82
+
83
+ #######
84
+ # GetText options
85
+ #######
86
+
87
+ self.disable_gettext = false
88
+
89
+ # Cf. https://github.com/translation/rails#gettext-object-class-monkey-patching
90
+ self.gettext_object_delegate = true
91
+
92
+ # GetText directory for PO and MO files
93
+ self.locales_path = File.join('config', 'locales', 'gettext')
94
+
95
+ # These paths and files will not be parsed for GetText entries
96
+ self.ignored_source_paths = ['vendor/', 'tmp/', 'node_modules/', 'logs/', '.git/', 'public/', 'private/']
97
+ self.ignored_source_files = []
98
+
99
+ # These gems will be parsed by GetText (use gem names)
100
+ self.parsed_gems = []
101
+
102
+ # Extensions for rb/erb/haml/slim file parsers
103
+ self.source_formats = ['rb', 'ruby', 'rabl']
104
+ self.erb_source_formats = ['erb', 'inky']
105
+ self.haml_source_formats = ['haml', 'mjmlhaml']
106
+ self.slim_source_formats = ['slim', 'mjmlslim']
107
+
108
+ # 'text_domain' will be synced (name of .po/.mo files)
109
+ # 'bound_text_domains' will be read during execution (in that priority order)
110
+ self.text_domain = 'app'
111
+ self.bound_text_domains = ['app']
112
+ self.charset = 'UTF-8'
113
+
114
+ # POT header informations
115
+ self.pot_msgid_bugs_address = 'contact@translation.io'
116
+ self.pot_package_name = File.basename(Dir.pwd)
117
+ self.pot_package_version = '1.0'
118
+ self.pot_copyright_holder = File.basename(Dir.pwd)
119
+ self.pot_copyright_year = Date.today.year
57
120
  end
58
121
 
59
122
  def pot_path
60
- File.join(locales_path, "#{TEXT_DOMAIN}.pot")
123
+ File.join(locales_path, "#{text_domain}.pot")
61
124
  end
62
125
 
63
126
  def yaml_file_paths
@@ -83,19 +146,45 @@ module TranslationIO
83
146
  end
84
147
 
85
148
  def source_files_for_formats(formats)
86
- file_paths = Dir["**/*.{#{formats.join(',')}}"]
87
-
88
- # remove ignored files
89
- file_paths = file_paths - ignored_source_files
149
+ file_paths = []
150
+ root_paths = ['.']
151
+
152
+ # Add gem paths that need to be parsed by GetText ("parsed_gem" option)
153
+ parsed_gems.each do |gem_name|
154
+ if Gem.loaded_specs[gem_name]
155
+ root_paths << Gem.loaded_specs[gem_name].full_gem_path
156
+ end
157
+ end
90
158
 
91
- # remove ignored paths
92
- ignored_source_paths.each do |ignored_source_path|
93
- file_paths = file_paths.select { |file_path| !file_path.start_with?(ignored_source_path) }
159
+ root_paths.each do |root_path|
160
+ Pathname.new(root_path).find do |path|
161
+ if path.directory?
162
+ if is_ignored_path?(path)
163
+ Find.prune
164
+ end
165
+ else
166
+ if formats.include?(path.extname[1..-1]) && !is_ignored_file?(path)
167
+ file_paths << path.to_s
168
+ end
169
+ end
170
+ end
94
171
  end
95
172
 
96
173
  file_paths
97
174
  end
98
175
 
176
+ def is_ignored_path?(path)
177
+ ignored_source_paths.any? do |ignored_source_path|
178
+ path == Pathname.new(ignored_source_path).cleanpath
179
+ end
180
+ end
181
+
182
+ def is_ignored_file?(path)
183
+ ignored_source_files.any? do |ignored_source_file|
184
+ path == Pathname.new(ignored_source_file).cleanpath
185
+ end
186
+ end
187
+
99
188
  def to_s
100
189
  "API Key: #{api_key} | Languages: #{source_locale} => [#{target_locales.join(', ')}]"
101
190
  end
@@ -7,9 +7,13 @@ module TranslationIO
7
7
  get_flat_hash_for_level(hash)
8
8
  end
9
9
 
10
- def to_hash(flat_hash)
10
+ def to_hash(flat_hash, remove_empty_keys = false)
11
11
  hash = {}
12
12
 
13
+ if remove_empty_keys
14
+ flat_hash = flat_hash.reject { |k, v| v.blank? && !k.end_with?(']') }
15
+ end
16
+
13
17
  flat_hash.each_pair do |key, value|
14
18
  build_hash_with_flat(hash, key, value)
15
19
  end
@@ -7,8 +7,10 @@ module TranslationIO
7
7
  require 'translation_io/tasks'
8
8
  end
9
9
 
10
- initializer 'translation.rails_extensions' do
11
- ActionController::Base.send(:include, TranslationIO::Controller)
10
+ initializer 'translation.controller_helper' do
11
+ ActiveSupport.on_load :action_controller do
12
+ ActionController::Base.send(:include, TranslationIO::Controller)
13
+ end
12
14
  end
13
15
 
14
16
  config.after_initialize do
@@ -49,8 +51,12 @@ if defined?(GetText)
49
51
  begin
50
52
  parse_path(path, po)
51
53
  rescue SystemExit => e
52
- # puts(_("Error parsing %{path}") % {:path => path})
53
54
  puts
55
+ puts "---------------"
56
+ puts "Error while parsing this file for GetText: #{path}"
57
+ puts "Are you sure the file is correctly formatted?"
58
+ puts "Feel free to contact us to get some help: contact@translation.io"
59
+ puts "---------------"
54
60
  puts
55
61
  end
56
62
  end
@@ -36,8 +36,16 @@ module TranslationIO
36
36
  end
37
37
 
38
38
  def get_yaml_data_from_flat_translations(flat_translations)
39
- translations = FlatHash.to_hash(flat_translations)
40
- return translations.to_yaml
39
+ remove_empty_keys = TranslationIO.config.yaml_remove_empty_keys
40
+ translations = FlatHash.to_hash(flat_translations, remove_empty_keys)
41
+
42
+ if TranslationIO.config.yaml_line_width
43
+ data = translations.to_yaml(:line_width => TranslationIO.config.yaml_line_width)
44
+ else
45
+ data = translations.to_yaml
46
+ end
47
+
48
+ data.gsub(/ $/, '') # remove trailing spaces
41
49
  end
42
50
 
43
51
  end
@@ -2,7 +2,7 @@ module TranslationIO
2
2
  module YamlEntry
3
3
 
4
4
  IGNORED_KEY_PREFIXES = [
5
- 'faker.'
5
+ 'faker'
6
6
  ]
7
7
 
8
8
  LOCALIZATION_KEY_PREFIXES = [
@@ -31,7 +31,7 @@ module TranslationIO
31
31
  end
32
32
 
33
33
  def ignored?(key)
34
- key.present? && ignored_key_prefixes.any? { |p| key_without_locale(key).start_with?(p) }
34
+ key.present? && ignored_key_prefixes.any? { |prefix| key_without_locale(key).match(/^#{Regexp.escape(prefix)}\b/) != nil }
35
35
  end
36
36
 
37
37
  def localization?(key, value)
@@ -40,7 +40,7 @@ module TranslationIO
40
40
 
41
41
  def localization_prefix?(key)
42
42
  localization_key_prefixes.any? do |prefix|
43
- key_without_locale(key).start_with?(prefix)
43
+ key_without_locale(key).match(/^#{Regexp.escape(prefix)}\b/) != nil
44
44
  end
45
45
  end
46
46
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: translation
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.17'
4
+ version: '1.22'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Hoste
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-11-12 00:00:00.000000000 Z
12
+ date: 2020-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gettext
@@ -35,30 +35,30 @@ dependencies:
35
35
  name: rake
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '12.0'
41
41
  type: :development
42
42
  prerelease: false
43
43
  version_requirements: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '12.0'
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: simplecov
50
50
  requirement: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '0.11'
55
55
  type: :development
56
56
  prerelease: false
57
57
  version_requirements: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.11'
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rspec
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -144,10 +144,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
144
  version: '0'
145
145
  requirements: []
146
146
  rubyforge_project:
147
- rubygems_version: 2.5.1
147
+ rubygems_version: 2.7.6
148
148
  signing_key:
149
149
  specification_version: 4
150
150
  summary: Localize your app with YAML or GetText. Synchronize with your translators
151
151
  on Translation.io.
152
152
  test_files: []
153
- has_rdoc: false