translation 1.19 → 1.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +189 -59
- data/lib/translation.rb +21 -8
- data/lib/translation_io/client/base_operation/save_special_yaml_files_step.rb +5 -3
- data/lib/translation_io/client/base_operation/update_pot_file_step.rb +23 -6
- data/lib/translation_io/client/base_operation.rb +32 -0
- data/lib/translation_io/client/init_operation/cleanup_yaml_files_step.rb +1 -1
- data/lib/translation_io/client/init_operation/create_yaml_po_files_step.rb +1 -1
- data/lib/translation_io/client/init_operation.rb +4 -2
- data/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb +110 -61
- data/lib/translation_io/client/sync_operation/create_yaml_pot_file_step.rb +1 -1
- data/lib/translation_io/client/sync_operation.rb +4 -2
- data/lib/translation_io/config.rb +6 -1
- data/lib/translation_io/flat_hash.rb +1 -1
- data/lib/translation_io/railtie.rb +4 -2
- data/lib/translation_io/yaml_conversion.rb +9 -3
- data/lib/translation_io/yaml_entry.rb +2 -2
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a34c57ba0de5df8e9d6e302e24d1d959db4b2a697678d7cfc67e08b36702ef6
|
4
|
+
data.tar.gz: 5e024618fe204efef1a26294ec9e8bb6ab5fe357d9a32d826623a7ed4a5b508b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59e48c919c27811c8d8ba6f1b29104d9adf2b661ce69a156acaea8ea669d137d87c9a07f0cb2e9e7f8175ca1930419d0ee6f1752fb4abb045fbfea9795185ea9
|
7
|
+
data.tar.gz: c2e556ccaf8f3bec9c833a51ba181c996e76f8f549cb1a180779ba287a9ac56ad992cf8b8fddb40bdb574cb63a3b6130145fe6a09a7d6f93af18dfbad43239af
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# [Translation.io](https://translation.io) client for Ruby on Rails
|
2
2
|
|
3
|
-
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE
|
4
|
-
[![Build Status](https://
|
5
|
-
[![Test Coverage](https://codeclimate.com/github/translation/rails/badges/coverage.svg)](https://codeclimate.com/github/translation/rails/
|
6
|
-
[![Gem Version](https://
|
3
|
+
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
|
4
|
+
[![Build Status](https://github.com/translation/rails/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/translation/rails/actions/workflows/test.yml)
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/translation/rails/badges/coverage.svg)](https://codeclimate.com/github/translation/rails/test_coverage)
|
6
|
+
[![Gem Version](https://badgen.net/rubygems/v/translation)](https://rubygems.org/gems/translation)
|
7
7
|
[![Downloads](https://img.shields.io/gem/dt/translation.svg)](https://rubygems.org/gems/translation)
|
8
8
|
|
9
|
-
Add this gem to localize your Ruby on Rails application.
|
9
|
+
Add this gem to localize your **Ruby on Rails** application.
|
10
10
|
|
11
11
|
Use the official Rails syntax (with [YAML](#i18n-yaml) files) or use the [GetText](#gettext) syntax.
|
12
12
|
|
@@ -35,25 +35,30 @@ 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)
|
42
|
+
* [Frontend Localization](#frontend-localization)
|
43
|
+
* [Using this Gem](#using-this-gem)
|
44
|
+
* [Using our official React & JavaScript package](#using-our-official-react--javascript-package)
|
41
45
|
* [Continuous Integration](#continuous-integration)
|
42
46
|
* [Advanced Configuration Options](#advanced-configuration-options)
|
43
47
|
* [Disable GetText or YAML](#disable-gettext-or-yaml)
|
44
48
|
* [Ignored YAML keys](#ignored-yaml-keys)
|
49
|
+
* [Custom localization key prefixes](#custom-localization-key-prefixes)
|
45
50
|
* [Source file formats (for GetText)](#source-file-formats-for-gettext)
|
46
51
|
* [Gems with GetText strings](#gems-with-gettext-strings)
|
47
|
-
* [Custom localization key prefixes](#custom-localization-key-prefixes)
|
48
52
|
* [Paths where locales are stored (not recommended)](#paths-where-locales-are-stored-not-recommended)
|
49
53
|
* [GetText Object Class Monkey-Patching](#gettext-object-class-monkey-patching)
|
50
54
|
* [Pure Ruby (without Rails)](#pure-ruby-without-rails)
|
55
|
+
* [Limitations](#limitations)
|
51
56
|
* [Testing](#testing)
|
52
57
|
* [Contributing](#contributing)
|
53
58
|
* [List of clients for Translation.io](#list-of-clients-for-translationio)
|
54
59
|
* [Ruby on Rails (Ruby)](#ruby-on-rails-ruby)
|
55
60
|
* [Laravel (PHP)](#laravel-php)
|
56
|
-
* [React and
|
61
|
+
* [React, React Native and JavaScript](#react-react-native-and-javascript)
|
57
62
|
* [Others](#others)
|
58
63
|
* [License](#license)
|
59
64
|
|
@@ -94,7 +99,7 @@ You can keep your source YAML file automatically updated using [i18n-tasks](http
|
|
94
99
|
This gem adds the GetText support to Rails. We [strongly suggest](https://translation.io/blog/gettext-is-better-than-rails-i18n)
|
95
100
|
that you use GetText to translate your application since it allows an easier and more complete syntax.
|
96
101
|
|
97
|
-
|
102
|
+
Moreover, you won't need to create and manage any YAML file since your code will be
|
98
103
|
automatically scanned for any string to translate.
|
99
104
|
|
100
105
|
```ruby
|
@@ -143,7 +148,7 @@ end
|
|
143
148
|
$ bundle exec rake translation:init
|
144
149
|
```
|
145
150
|
|
146
|
-
If you
|
151
|
+
If you need to add or remove languages in the future, please read our
|
147
152
|
[documentation](https://translation.io/blog/adding-target-languages) about that.
|
148
153
|
|
149
154
|
## Usage
|
@@ -176,7 +181,8 @@ $ bundle exec rake translation:sync_and_purge
|
|
176
181
|
|
177
182
|
As the name says, this operation will also perform a sync at the same time.
|
178
183
|
|
179
|
-
Warning: all keys that are not present in the current branch
|
184
|
+
Warning: all keys that are not present in the current local branch
|
185
|
+
will be **permanently deleted from Translation.io**.
|
180
186
|
|
181
187
|
## Manage Languages
|
182
188
|
|
@@ -204,24 +210,39 @@ Since you created a new project, the translation history and tags will unfortuna
|
|
204
210
|
|
205
211
|
### Custom Languages
|
206
212
|
|
207
|
-
|
208
|
-
|
209
|
-
|
213
|
+
Custom languages are convenient if you want to customize translations for a specific customer
|
214
|
+
or another instance of your application.
|
215
|
+
|
216
|
+
A custom language is always be derived from an [existing language](https://translation.io/docs/languages).
|
217
|
+
Its structure should be like:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
"#{existing_language_code}-#{custom_text}"
|
221
|
+
```
|
210
222
|
|
211
|
-
|
223
|
+
where `custom_text` can only contain alphabetic characters and `-`.
|
212
224
|
|
213
225
|
Examples: `en-microsoft` or `fr-BE-custom`.
|
214
226
|
|
215
|
-
|
216
|
-
It means that if the `en-microsoft.some_key` is missing, then it will fallback to
|
217
|
-
`en.some_key`. So you only need to translate keys that should be customized.
|
227
|
+
### Fallbacks
|
218
228
|
|
219
|
-
|
220
|
-
|
229
|
+
If a translation is missing for a regional (`fr-BE`) or custom (`fr-microsoft`)
|
230
|
+
language, then it will fallback to the main language (`fr`).
|
221
231
|
|
222
|
-
|
223
|
-
|
224
|
-
|
232
|
+
Locale fallbacks will work as expected with both [I18n (YAML)](#i18n-yaml)
|
233
|
+
and [GetText](#gettext) syntaxes.
|
234
|
+
|
235
|
+
A good way to leverage this feature is to ignore sentences from a regional language
|
236
|
+
that would have the same translation as the main language (usually most of them).
|
237
|
+
It's way easier to maintain the project over time if only 10% of the regional sentences
|
238
|
+
need to be adapted.
|
239
|
+
|
240
|
+
Note that fallbacks are chained, so `fr-BE-custom` will fallback to `fr-BE` that will
|
241
|
+
fallback to `fr`.
|
242
|
+
|
243
|
+
Just make sure to add `config.i18n.fallbacks = true` to your `config/application.rb` file.
|
244
|
+
You can find more information about this
|
245
|
+
[here](https://guides.rubyonrails.org/configuring.html#configuring-i18n).
|
225
246
|
|
226
247
|
## Change the current locale
|
227
248
|
|
@@ -237,9 +258,12 @@ class ApplicationController < ActionController::Base
|
|
237
258
|
end
|
238
259
|
```
|
239
260
|
|
240
|
-
|
261
|
+
First time the user will connect, it will automatically set the locale extracted
|
262
|
+
from the user's browser `HTTP_ACCEPT_LANGUAGE` value, and keep it in the session between
|
263
|
+
requests.
|
241
264
|
|
242
|
-
Update the current locale by redirecting the user to https://yourdomain.com?locale=fr
|
265
|
+
Update the current locale by redirecting the user to https://yourdomain.com?locale=fr
|
266
|
+
or even https://yourdomain.com/fr if you scoped your routes like this:
|
243
267
|
|
244
268
|
```ruby
|
245
269
|
scope "/:locale", :constraints => { locale: /[a-z]{2}/ } do
|
@@ -247,9 +271,11 @@ scope "/:locale", :constraints => { locale: /[a-z]{2}/ } do
|
|
247
271
|
end
|
248
272
|
```
|
249
273
|
|
250
|
-
The `set_locale` code is [here](https://github.com/translation/rails/blob/master/lib/translation_io/controller.rb#L3),
|
274
|
+
The `set_locale` code is [here](https://github.com/translation/rails/blob/master/lib/translation_io/controller.rb#L3),
|
275
|
+
feel free to override it with your own locale management.
|
251
276
|
|
252
|
-
Don't forget to define your available locales with
|
277
|
+
Don't forget to define your available locales with
|
278
|
+
[I18n.available_locales](http://guides.rubyonrails.org/i18n.html#setup-the-rails-application-for-internationalization).
|
253
279
|
|
254
280
|
More examples here: https://translation.io/blog/set-current-locale-in-your-rails-app
|
255
281
|
|
@@ -265,17 +291,91 @@ You can call it several times in the same page if you want to switch between lan
|
|
265
291
|
|
266
292
|
More examples here: https://translation.io/blog/rails-i18n-with-locale
|
267
293
|
|
294
|
+
## Frontend Localization
|
295
|
+
|
296
|
+
### Using this Gem
|
297
|
+
|
298
|
+
This gem is also able to cover frontend localization (React, Vue, ...).
|
299
|
+
|
300
|
+
There are several ways to pass the translation strings from the backend
|
301
|
+
to the frontend: JavaScript serialization, `data-` HTML attributes, JSON files etc.
|
302
|
+
|
303
|
+
The easiest strategy when dealing with React/Vue would be to pass the corresponding
|
304
|
+
translations as props when mounting the components.
|
305
|
+
|
306
|
+
Assuming that you use [reactjs/react-rails](https://github.com/reactjs/react-rails),
|
307
|
+
it would look like this if you want to use [I18n (YAML)](#i18n-yaml) syntax:
|
308
|
+
|
309
|
+
```erb
|
310
|
+
<%=
|
311
|
+
react_component('MyComponent", {
|
312
|
+
:user_id => current_user.id,
|
313
|
+
:i18n => YAML.load_file("config/locales/#{I18n.locale}.yml")[I18n.locale.to_s]["my_component"]
|
314
|
+
})
|
315
|
+
%>
|
316
|
+
```
|
317
|
+
|
318
|
+
Your `en.yml` should look like this:
|
319
|
+
|
320
|
+
```yaml
|
321
|
+
en:
|
322
|
+
my_component:
|
323
|
+
your_name: Your name
|
324
|
+
title: Title
|
325
|
+
```
|
326
|
+
|
327
|
+
You can also directly use the [GetText](#gettext) syntax:
|
328
|
+
|
329
|
+
```erb
|
330
|
+
<%=
|
331
|
+
react_component('MyComponent", {
|
332
|
+
:user_id => current_user.id,
|
333
|
+
:i18n => {
|
334
|
+
:your_name => _('Your name'),
|
335
|
+
:title => _('Title')
|
336
|
+
}
|
337
|
+
})
|
338
|
+
%>
|
339
|
+
```
|
340
|
+
|
341
|
+
In both case, in your React component, you can simply call
|
342
|
+
`this.props.i18n.yourName` and your text will be localized with the current locale.
|
343
|
+
|
344
|
+
**Notes:**
|
345
|
+
|
346
|
+
* You can also structure the i18n props with multiple levels of depth and pass the subtree as props to each of your sub-components.
|
347
|
+
* It also works great with server-side rendering of your components (`:prerender => true`).
|
348
|
+
|
349
|
+
### Using our official React & JavaScript package
|
350
|
+
|
351
|
+
As Translation.io is directly integrated in the great
|
352
|
+
[Lingui](https://lingui.js.org/) internationalization framework,
|
353
|
+
you can also consider frontend localization as a completely different
|
354
|
+
localization project.
|
355
|
+
|
356
|
+
Please read more about this on:
|
357
|
+
|
358
|
+
* Website: [https://translation.io/lingui](https://translation.io/lingui)
|
359
|
+
* GitHub page: [https://github.com/translation/lingui](https://github.com/translation/lingui)
|
360
|
+
|
268
361
|
## Continuous Integration
|
269
362
|
|
270
|
-
If you want fresh translations in your Continuous Integration workflow, you may
|
363
|
+
If you want fresh translations in your Continuous Integration workflow, you may
|
364
|
+
find yourself calling `bundle exec rake translation:sync` very frequently.
|
271
365
|
|
272
|
-
Since this task can't be concurrently executed
|
366
|
+
Since this task can't be concurrently executed
|
367
|
+
(we have a [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) strategy with
|
368
|
+
a queue but it returns an error under heavy load), we implemented this
|
369
|
+
threadsafe readonly task:
|
273
370
|
|
274
371
|
```bash
|
275
372
|
$ bundle exec rake translation:sync_readonly
|
276
373
|
```
|
277
374
|
|
278
|
-
This task will prevent your CI to fail and still provide new translations. But
|
375
|
+
This task will prevent your CI to fail and still provide new translations. But
|
376
|
+
be aware that it won't send new keys from your code to Translation.io so you
|
377
|
+
still need to call `bundle exec rake translation:sync` at some point during
|
378
|
+
development.
|
279
379
|
|
280
380
|
## Advanced Configuration Options
|
281
381
|
|
@@ -330,6 +430,32 @@ TranslationIO.configure do |config|
|
|
330
430
|
end
|
331
431
|
```
|
332
432
|
|
433
|
+
### Custom localization key prefixes
|
434
|
+
|
435
|
+
Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans)
|
436
|
+
in the same place and that's bad. For example: date formats, number separators, default
|
437
|
+
currency or measure units, etc.
|
438
|
+
|
439
|
+
A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or
|
440
|
+
numbers to be displayed, right? Moreover, this special keys often contain special constructions (e.g.,
|
441
|
+
with percent signs or spaces) that he might break.
|
442
|
+
|
443
|
+
We think localization is part of the configuration of the app and it should not reach the translator UI at all.
|
444
|
+
That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.
|
445
|
+
|
446
|
+
We automatically treat [known localization keys](lib/translation_io/yaml_entry.rb), but if you would like
|
447
|
+
to add some more, use the `localization_key_prefixes` option.
|
448
|
+
|
449
|
+
For example:
|
450
|
+
|
451
|
+
```ruby
|
452
|
+
TranslationIO.configure do |config|
|
453
|
+
...
|
454
|
+
config.localization_key_prefixes = ['my_gem.date.formats']
|
455
|
+
...
|
456
|
+
end
|
457
|
+
```
|
458
|
+
|
333
459
|
### Source file formats (for GetText)
|
334
460
|
|
335
461
|
If you are using GetText and you want to manage other file formats than:
|
@@ -365,32 +491,6 @@ TranslationIO.configure do |config|
|
|
365
491
|
end
|
366
492
|
```
|
367
493
|
|
368
|
-
### Custom localization key prefixes
|
369
|
-
|
370
|
-
Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans)
|
371
|
-
in the same place and that's bad. For example: date formats, number separators, default
|
372
|
-
currency or measure units, etc.
|
373
|
-
|
374
|
-
A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or
|
375
|
-
numbers to be displayed, right? Moreover, this special keys often contain special constructions (e.g.,
|
376
|
-
with percent signs or spaces) that he might break.
|
377
|
-
|
378
|
-
We think localization is part of the configuration of the app and it should not reach the translator UI at all.
|
379
|
-
That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.
|
380
|
-
|
381
|
-
We automatically treat [known localization keys](lib/translation_io/yaml_entry.rb), but if you would like
|
382
|
-
to add some more, use the `localization_key_prefixes` option.
|
383
|
-
|
384
|
-
For example:
|
385
|
-
|
386
|
-
```ruby
|
387
|
-
TranslationIO.configure do |config|
|
388
|
-
...
|
389
|
-
config.localization_key_prefixes = ['my_gem.date.formats']
|
390
|
-
...
|
391
|
-
end
|
392
|
-
```
|
393
|
-
|
394
494
|
### Paths where locales are stored (not recommended)
|
395
495
|
|
396
496
|
You can specify where your GetText and YAML files are on disk:
|
@@ -483,6 +583,33 @@ This gem was created specifically for Rails, but you can also use it in a pure R
|
|
483
583
|
|
484
584
|
(Thanks [@kubaw](https://github.com/kubaw) for this snippet!)
|
485
585
|
|
586
|
+
## Limitations
|
587
|
+
|
588
|
+
If you localize `.erb` files with the [GetText syntax](#gettext), please avoid
|
589
|
+
the use of `case` and `when` that are not correctly parsed by ERB.
|
590
|
+
|
591
|
+
This syntax will break and your file will be ignored:
|
592
|
+
|
593
|
+
```erb
|
594
|
+
<% case @state %>
|
595
|
+
<% when 'received' %>
|
596
|
+
```
|
597
|
+
|
598
|
+
Instead, use `if`/`elsif` or this `case` syntax:
|
599
|
+
|
600
|
+
```erb
|
601
|
+
<%
|
602
|
+
case @state
|
603
|
+
when 'received'
|
604
|
+
%>
|
605
|
+
```
|
606
|
+
|
607
|
+
These are the related discussions: [ruby/erb#4](https://github.com/ruby/erb/issues/4) and [translation/rails#44](https://github.com/translation/rails/issues/44).
|
608
|
+
|
609
|
+
There is currently an open PR ([ruby-gettext/gettext#91](https://github.com/ruby-gettext/gettext/pull/91)), switching ERB for [Erubi](https://github.com/jeremyevans/erubi),
|
610
|
+
that is waiting to be merged into GetText, but it may have unknown undesirable
|
611
|
+
side effects.
|
612
|
+
|
486
613
|
## Testing
|
487
614
|
|
488
615
|
To run the specs:
|
@@ -521,12 +648,15 @@ Officially Supported on [https://translation.io/laravel](https://translation.io/
|
|
521
648
|
|
522
649
|
Credits: [@armandsar](https://github.com/armandsar), [@michaelhoste](https://github.com/michaelhoste)
|
523
650
|
|
524
|
-
### React and
|
651
|
+
### React, React Native and JavaScript
|
652
|
+
|
653
|
+
Officially Supported on [https://translation.io/lingui](https://translation.io/lingui)
|
525
654
|
|
526
|
-
|
527
|
-
|
655
|
+
Translation.io is directly integrated in the great
|
656
|
+
[Lingui](https://lingui.js.org/) internationalization project.
|
528
657
|
|
529
|
-
|
658
|
+
* GitHub: https://github.com/translation/lingui
|
659
|
+
* NPM: https://www.npmjs.com/package/@translation/lingui
|
530
660
|
|
531
661
|
### Others
|
532
662
|
|
data/lib/translation.rb
CHANGED
@@ -33,13 +33,16 @@ module TranslationIO
|
|
33
33
|
|
34
34
|
if !@config.disable_gettext
|
35
35
|
require_gettext_dependencies
|
36
|
-
add_missing_locales
|
37
36
|
add_parser_for_erb_source_formats(@config.erb_source_formats)
|
38
37
|
|
39
38
|
if Rails.env.development?
|
40
39
|
GetText::TextDomainManager.cached = false
|
41
40
|
end
|
42
41
|
|
42
|
+
# Set default GetText locale (last fallback) as config.source_locale instead of "en" (default)
|
43
|
+
gettext_locale = @config.source_locale.to_s.gsub('-', '_').to_sym
|
44
|
+
Locale.set_default(gettext_locale)
|
45
|
+
|
43
46
|
# include is private until Ruby 2.1
|
44
47
|
Proxy.send(:include, GetText)
|
45
48
|
|
@@ -69,19 +72,20 @@ module TranslationIO
|
|
69
72
|
require 'gettext/tools'
|
70
73
|
require 'gettext/text_domain_manager'
|
71
74
|
require 'gettext/tools/xgettext'
|
72
|
-
|
73
|
-
|
74
|
-
# Missing languages from Locale that are in Translation.io
|
75
|
-
def add_missing_locales
|
76
|
-
Locale::Info.three_languages['wee'] = Locale::Info::Language.new('', 'wee', 'I', 'L', 'Lower Sorbian')
|
77
|
-
Locale::Info.three_languages['wen'] = Locale::Info::Language.new('', 'wen', 'I', 'L', 'Upper Sorbian')
|
75
|
+
require "gettext/tools/parser/erubi" if Gem::Version.new(GetText::VERSION) >= Gem::Version.new('3.4.3')
|
78
76
|
end
|
79
77
|
|
80
78
|
def add_parser_for_erb_source_formats(new_erb_formats)
|
81
|
-
existing_extensions = GetText::ErbParser.instance_variable_get("@config")[:extnames]
|
82
79
|
new_extensions = new_erb_formats.collect { |ext| ".#{ext}" }
|
83
80
|
|
81
|
+
existing_extensions = GetText::ErbParser.instance_variable_get("@config")[:extnames]
|
84
82
|
GetText::ErbParser.instance_variable_get("@config")[:extnames] = (existing_extensions + new_extensions).uniq
|
83
|
+
|
84
|
+
# for gettext >= 3.4.3 (erubi compatibility)
|
85
|
+
if defined?(GetText::ErubiParser)
|
86
|
+
existing_extensions = GetText::ErubiParser.instance_variable_get("@config")[:extnames]
|
87
|
+
GetText::ErubiParser.instance_variable_get("@config")[:extnames] = (existing_extensions + new_extensions).uniq
|
88
|
+
end
|
85
89
|
end
|
86
90
|
|
87
91
|
def info(message, level = 0, verbose_level = 0)
|
@@ -96,6 +100,15 @@ module TranslationIO
|
|
96
100
|
File.expand_path(relative_or_absolute_path).gsub("#{Dir.pwd}/", '')
|
97
101
|
end
|
98
102
|
|
103
|
+
# Cf. https://github.com/translation/rails/issues/47
|
104
|
+
def yaml_load(source)
|
105
|
+
begin
|
106
|
+
YAML.load(source, :aliases => true) || {}
|
107
|
+
rescue ArgumentError
|
108
|
+
YAML.load(source) || {}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
99
112
|
def version
|
100
113
|
Gem::Specification::find_by_name('translation').version.to_s
|
101
114
|
end
|
@@ -35,13 +35,15 @@ module TranslationIO
|
|
35
35
|
YamlEntry.from_locale?(key, target_locale) && !YamlEntry.ignored?(key)
|
36
36
|
end
|
37
37
|
|
38
|
-
yaml_data = YAMLConversion.get_yaml_data_from_flat_translations(target_flat_special_translations
|
38
|
+
yaml_data = YAMLConversion.get_yaml_data_from_flat_translations(target_flat_special_translations, **{
|
39
|
+
:force_keep_empty_keys => true # We want to keep empty keys from localization.xx.yml files (sometimes needed for delimiters!)
|
40
|
+
})
|
39
41
|
|
40
42
|
params["yaml_data_#{target_locale}"] = yaml_data
|
41
43
|
|
42
44
|
# To have a localization.xx.yml file during tests (without call to backend)
|
43
45
|
if TranslationIO.config.test
|
44
|
-
if
|
46
|
+
if TranslationIO.yaml_load(yaml_data).present?
|
45
47
|
File.open(yaml_path, 'wb') do |file|
|
46
48
|
file.write(self.class.top_comment)
|
47
49
|
file.write(yaml_data)
|
@@ -62,7 +64,7 @@ module TranslationIO
|
|
62
64
|
yaml_path = File.join(@yaml_locales_path, "localization.#{target_locale}.yml")
|
63
65
|
yaml_data = parsed_response["yaml_data_#{target_locale}"]
|
64
66
|
|
65
|
-
if yaml_data.present? &&
|
67
|
+
if yaml_data.present? && TranslationIO.yaml_load(yaml_data).present?
|
66
68
|
File.open(yaml_path, 'wb') do |file|
|
67
69
|
file.write(self.class.top_comment)
|
68
70
|
file.write(yaml_data)
|
@@ -16,12 +16,29 @@ module TranslationIO
|
|
16
16
|
TranslationIO.info "Updating POT file."
|
17
17
|
|
18
18
|
FileUtils.mkdir_p(File.dirname(@pot_path))
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
|
20
|
+
# for gettext >= 3.4.3 (erubi compatibility)
|
21
|
+
if defined?(GetText::ErubiParser)
|
22
|
+
GetText::Tools::XGetText.run(
|
23
|
+
*@source_files, '-o', @pot_path,
|
24
|
+
'--msgid-bugs-address', TranslationIO.config.pot_msgid_bugs_address,
|
25
|
+
'--package-name', TranslationIO.config.pot_package_name,
|
26
|
+
'--package-version', TranslationIO.config.pot_package_version,
|
27
|
+
'--copyright-holder', TranslationIO.config.pot_copyright_holder,
|
28
|
+
'--copyright-year', TranslationIO.config.pot_copyright_year.to_s,
|
29
|
+
'--require', 'gettext/tools/parser/erubi', # Cf. (1) https://github.com/ruby-gettext/gettext/pull/91
|
30
|
+
'--parser', 'GetText::ErubiParser' # (2) https://github.com/ruby-gettext/gettext/commit/0eb06a88323a5cc16065680ffe228d978fb87c88
|
31
|
+
)
|
32
|
+
else
|
33
|
+
GetText::Tools::XGetText.run(
|
34
|
+
*@source_files, '-o', @pot_path,
|
35
|
+
'--msgid-bugs-address', TranslationIO.config.pot_msgid_bugs_address,
|
36
|
+
'--package-name', TranslationIO.config.pot_package_name,
|
37
|
+
'--package-version', TranslationIO.config.pot_package_version,
|
38
|
+
'--copyright-holder', TranslationIO.config.pot_copyright_holder,
|
39
|
+
'--copyright-year', TranslationIO.config.pot_copyright_year.to_s
|
40
|
+
)
|
41
|
+
end
|
25
42
|
|
26
43
|
FileUtils.rm_f(@tmp_empty_file) if @tmp_empty_file.present?
|
27
44
|
|
@@ -17,6 +17,38 @@ module TranslationIO
|
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
+
def warn_wrong_locales(source_locale, target_locales)
|
21
|
+
if target_locales.uniq != target_locales
|
22
|
+
duplicate_locale = target_locales.detect { |locale| target_locales.count(locale) > 1 }
|
23
|
+
|
24
|
+
puts
|
25
|
+
puts "----------"
|
26
|
+
puts "Your `config.target_locales` has a duplicate locale (#{duplicate_locale})."
|
27
|
+
puts "Please clean your configuration file and execute this command again."
|
28
|
+
puts "----------"
|
29
|
+
exit(true)
|
30
|
+
end
|
31
|
+
|
32
|
+
if target_locales.include?(source_locale)
|
33
|
+
puts
|
34
|
+
puts "----------"
|
35
|
+
puts "The `config.source_locale` (#{source_locale}) can't be included in the `config.target_locales`."
|
36
|
+
puts "If you want to customize your source locale, check this link: https://github.com/translation/rails#custom-languages"
|
37
|
+
puts "Please clean your configuration file and execute this command again."
|
38
|
+
puts "----------"
|
39
|
+
exit(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
if target_locales.empty?
|
43
|
+
puts
|
44
|
+
puts "----------"
|
45
|
+
puts "Your `config.target_locales` is empty."
|
46
|
+
puts "Please clean your configuration file and execute this command again."
|
47
|
+
puts "----------"
|
48
|
+
exit(true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
20
52
|
def self.perform_request(uri, params)
|
21
53
|
begin
|
22
54
|
params.merge!({
|
@@ -13,7 +13,7 @@ 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 =
|
16
|
+
content_hash = TranslationIO.yaml_load(File.read(locale_file_path)) || {}
|
17
17
|
source_content_hash = content_hash.select { |k| k.to_s == @source_locale.to_s }
|
18
18
|
|
19
19
|
if source_content_hash.empty?
|
@@ -18,7 +18,7 @@ module TranslationIO
|
|
18
18
|
|
19
19
|
@yaml_file_paths.each do |file_path|
|
20
20
|
TranslationIO.info file_path, 2, 2
|
21
|
-
file_translations =
|
21
|
+
file_translations = TranslationIO.yaml_load(File.read(file_path))
|
22
22
|
|
23
23
|
unless file_translations.blank?
|
24
24
|
all_translations = all_translations.deep_merge(file_translations)
|
@@ -13,12 +13,14 @@ module TranslationIO
|
|
13
13
|
haml_source_files = config.haml_source_files
|
14
14
|
slim_source_files = config.slim_source_files
|
15
15
|
pot_path = config.pot_path
|
16
|
-
source_locale = config.source_locale
|
17
|
-
target_locales = config.target_locales
|
16
|
+
source_locale = config.source_locale.to_s
|
17
|
+
target_locales = config.target_locales.map(&:to_s)
|
18
18
|
locales_path = config.locales_path
|
19
19
|
yaml_locales_path = config.yaml_locales_path
|
20
20
|
yaml_file_paths = config.yaml_file_paths
|
21
21
|
|
22
|
+
warn_wrong_locales(source_locale, target_locales)
|
23
|
+
|
22
24
|
if !config.disable_gettext
|
23
25
|
BaseOperation::DumpMarkupGettextKeysStep.new(haml_source_files, :haml).run
|
24
26
|
BaseOperation::DumpMarkupGettextKeysStep.new(slim_source_files, :slim).run
|
@@ -12,72 +12,113 @@ 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
|
-
|
17
|
-
TranslationIO.info "Applying YAML source editions."
|
17
|
+
TranslationIO.info "Applying YAML source editions."
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
source_edits.each do |source_edit|
|
20
|
+
applied = false
|
21
21
|
|
22
|
-
|
23
|
-
yaml_hash = YAML::load(File.read(file_path))
|
24
|
-
flat_yaml_hash = FlatHash.to_flat_hash(yaml_hash)
|
22
|
+
reload_or_reuse_yaml_sources
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
TranslationIO.info "#{source_edit['key']} | #{source_edit['old_text']} -> #{source_edit['new_text']}", 2, 2
|
24
|
+
@yaml_sources.to_a.each do |yaml_source|
|
25
|
+
yaml_file_path = yaml_source[:yaml_file_path]
|
26
|
+
yaml_flat_hash = yaml_source[:yaml_flat_hash]
|
30
27
|
|
31
|
-
|
32
|
-
|
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
|
34
|
+
end
|
33
35
|
|
34
|
-
|
36
|
+
break if applied
|
37
|
+
end
|
38
|
+
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
else # override source text of gem
|
40
|
-
yaml_path = File.join(TranslationIO.config.yaml_locales_path, "#{@source_locale}.yml")
|
40
|
+
update_metadata_timestamp
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
yaml_hash = YAML::load(File.read(yaml_path))
|
44
|
-
flat_yaml_hash = FlatHash.to_flat_hash(yaml_hash)
|
45
|
-
else
|
46
|
-
FileUtils::mkdir_p File.dirname(yaml_path)
|
47
|
-
flat_yaml_hash = {}
|
48
|
-
end
|
43
|
+
private
|
49
44
|
|
50
|
-
|
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 = TranslationIO.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_source
|
59
|
+
end
|
60
|
+
end
|
51
61
|
|
52
|
-
|
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
|
53
75
|
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
76
|
+
def apply_source_edit(source_edit, yaml_file_path, yaml_flat_hash)
|
77
|
+
full_key = "#{@source_locale}.#{source_edit['key']}"
|
58
78
|
|
59
|
-
|
60
|
-
|
61
|
-
else
|
62
|
-
TranslationIO.info "#{source_edit['key']} | Ignored because translation was also updated in source YAML file", 2, 2
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
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
|
66
81
|
|
67
|
-
|
68
|
-
|
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)
|
69
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
|
70
89
|
end
|
90
|
+
end
|
71
91
|
|
72
|
-
|
73
|
-
|
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)
|
74
99
|
end
|
75
100
|
end
|
76
101
|
|
77
|
-
|
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"))
|
78
105
|
|
79
|
-
|
80
|
-
|
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)
|
81
122
|
|
82
123
|
if TranslationIO.config.yaml_line_width
|
83
124
|
content = yaml_hash.to_yaml(:line_width => TranslationIO.config.yaml_line_width)
|
@@ -92,37 +133,45 @@ module TranslationIO
|
|
92
133
|
if File.exist?(TranslationIO.config.metadata_path)
|
93
134
|
metadata_content = File.read(TranslationIO.config.metadata_path)
|
94
135
|
|
136
|
+
# If any conflicts in file, take the lowest timestamp and potentially reapply some source edits
|
95
137
|
if metadata_content.include?('>>>>') || metadata_content.include?('<<<<')
|
96
|
-
|
97
|
-
|
138
|
+
timestamps = metadata_content.scan(/timestamp: (\d*)/).flatten.uniq.collect(&:to_i)
|
139
|
+
return timestamps.min || 0
|
98
140
|
else
|
99
|
-
return YAML
|
141
|
+
return YAML.load(metadata_content)['timestamp'] rescue 0
|
100
142
|
end
|
101
143
|
else
|
102
144
|
return 0
|
103
145
|
end
|
104
146
|
end
|
105
147
|
|
148
|
+
def update_metadata_timestamp
|
149
|
+
File.open(TranslationIO.config.metadata_path, 'w') do |f|
|
150
|
+
f.puts '# This file is used in the context of Translation.io source editions.'
|
151
|
+
f.puts '# Please see: https://translation.io/blog/new-feature-copywriting'
|
152
|
+
f.puts '#'
|
153
|
+
f.puts '# If you have any git conflicts, either keep the smaller timestamp or'
|
154
|
+
f.puts '# ignore the conflicts and "sync" again, it will fix this file for you.'
|
155
|
+
f.puts
|
156
|
+
|
157
|
+
f.write({ 'timestamp' => Time.now.utc.to_i }.to_yaml)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
106
161
|
def perform_source_edits_request(params)
|
107
162
|
uri = URI("#{TranslationIO.client.endpoint}/projects/#{TranslationIO.client.api_key}/source_edits")
|
108
163
|
parsed_response = BaseOperation.perform_request(uri, params)
|
109
164
|
end
|
110
165
|
|
111
|
-
# Sort YAML file paths by project locales first, gem locales after
|
112
|
-
# (to replace "overridden" source first)
|
113
|
-
def sort_by_project_locales_first(yaml_file_paths)
|
114
|
-
yaml_file_paths.sort do |x, y|
|
115
|
-
a = locale_file_path_in_project?(x)
|
116
|
-
b = locale_file_path_in_project?(y)
|
117
|
-
(!a && b) ? 1 : ((a && !b) ? -1 : 0)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
166
|
def locale_file_path_in_project?(locale_file_path)
|
122
|
-
|
123
|
-
|
167
|
+
normalize_path(locale_file_path).start_with?(
|
168
|
+
normalize_path(TranslationIO.config.yaml_locales_path)
|
124
169
|
)
|
125
170
|
end
|
171
|
+
|
172
|
+
def normalize_path(path)
|
173
|
+
TranslationIO.normalize_path(path)
|
174
|
+
end
|
126
175
|
end
|
127
176
|
end
|
128
177
|
end
|
@@ -14,7 +14,7 @@ module TranslationIO
|
|
14
14
|
|
15
15
|
@yaml_file_paths.each do |file_path|
|
16
16
|
TranslationIO.info file_path, 2, 2
|
17
|
-
file_translations =
|
17
|
+
file_translations = TranslationIO.yaml_load(File.read(file_path))
|
18
18
|
|
19
19
|
unless file_translations.blank?
|
20
20
|
all_translations = all_translations.deep_merge(file_translations)
|
@@ -16,12 +16,14 @@ module TranslationIO
|
|
16
16
|
haml_source_files = config.haml_source_files
|
17
17
|
slim_source_files = config.slim_source_files
|
18
18
|
pot_path = config.pot_path
|
19
|
-
source_locale = config.source_locale
|
20
|
-
target_locales = config.target_locales
|
19
|
+
source_locale = config.source_locale.to_s
|
20
|
+
target_locales = config.target_locales.map(&:to_s)
|
21
21
|
locales_path = config.locales_path
|
22
22
|
yaml_locales_path = config.yaml_locales_path
|
23
23
|
yaml_file_paths = config.yaml_file_paths
|
24
24
|
|
25
|
+
warn_wrong_locales(source_locale, target_locales)
|
26
|
+
|
25
27
|
if !config.disable_yaml
|
26
28
|
ApplyYamlSourceEditsStep.new(yaml_file_paths, source_locale).run(params)
|
27
29
|
end
|
@@ -14,6 +14,7 @@ module TranslationIO
|
|
14
14
|
attr_accessor :ignored_key_prefixes
|
15
15
|
attr_accessor :localization_key_prefixes
|
16
16
|
attr_accessor :yaml_line_width
|
17
|
+
attr_accessor :yaml_remove_empty_keys
|
17
18
|
|
18
19
|
attr_accessor :disable_gettext
|
19
20
|
|
@@ -75,6 +76,10 @@ module TranslationIO
|
|
75
76
|
# Cf. https://github.com/translation/rails/issues/19
|
76
77
|
self.yaml_line_width = nil
|
77
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
|
+
|
78
83
|
#######
|
79
84
|
# GetText options
|
80
85
|
#######
|
@@ -119,7 +124,7 @@ module TranslationIO
|
|
119
124
|
end
|
120
125
|
|
121
126
|
def yaml_file_paths
|
122
|
-
I18n.load_path.select do |p|
|
127
|
+
I18n.load_path.collect(&:to_s).uniq.select do |p|
|
123
128
|
File.exist?(p) && (File.extname(p) == '.yml' || File.extname(p) == '.yaml')
|
124
129
|
end
|
125
130
|
end
|
@@ -7,8 +7,10 @@ module TranslationIO
|
|
7
7
|
require 'translation_io/tasks'
|
8
8
|
end
|
9
9
|
|
10
|
-
initializer 'translation.
|
11
|
-
|
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
|
@@ -26,7 +26,7 @@ module TranslationIO
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def get_flat_translations_for_yaml_data(yaml_data)
|
29
|
-
translations =
|
29
|
+
translations = TranslationIO.yaml_load(yaml_data)
|
30
30
|
|
31
31
|
if translations
|
32
32
|
return FlatHash.to_flat_hash(translations)
|
@@ -35,8 +35,14 @@ module TranslationIO
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def get_yaml_data_from_flat_translations(flat_translations)
|
39
|
-
|
38
|
+
def get_yaml_data_from_flat_translations(flat_translations, force_keep_empty_keys: false)
|
39
|
+
if force_keep_empty_keys
|
40
|
+
remove_empty_keys = false
|
41
|
+
else
|
42
|
+
remove_empty_keys = TranslationIO.config.yaml_remove_empty_keys
|
43
|
+
end
|
44
|
+
|
45
|
+
translations = FlatHash.to_hash(flat_translations, remove_empty_keys)
|
40
46
|
|
41
47
|
if TranslationIO.config.yaml_line_width
|
42
48
|
data = translations.to_yaml(:line_width => TranslationIO.config.yaml_line_width)
|
@@ -31,7 +31,7 @@ module TranslationIO
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def ignored?(key)
|
34
|
-
key.present? && ignored_key_prefixes.any? { |
|
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).match(/^#{prefix}\b/) != nil
|
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.
|
4
|
+
version: '1.32'
|
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:
|
12
|
+
date: 2022-05-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gettext
|
@@ -21,6 +21,9 @@ dependencies:
|
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 3.2.5
|
24
|
+
- - "<="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.4.3
|
24
27
|
type: :runtime
|
25
28
|
prerelease: false
|
26
29
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,6 +34,9 @@ dependencies:
|
|
31
34
|
- - ">="
|
32
35
|
- !ruby/object:Gem::Version
|
33
36
|
version: 3.2.5
|
37
|
+
- - "<="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 3.4.3
|
34
40
|
- !ruby/object:Gem::Dependency
|
35
41
|
name: rake
|
36
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -65,14 +71,14 @@ dependencies:
|
|
65
71
|
requirements:
|
66
72
|
- - "~>"
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
74
|
+
version: '3.0'
|
69
75
|
type: :development
|
70
76
|
prerelease: false
|
71
77
|
version_requirements: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
79
|
- - "~>"
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
81
|
+
version: '3.0'
|
76
82
|
- !ruby/object:Gem::Dependency
|
77
83
|
name: rails
|
78
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -143,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
149
|
- !ruby/object:Gem::Version
|
144
150
|
version: '0'
|
145
151
|
requirements: []
|
146
|
-
rubygems_version: 3.
|
152
|
+
rubygems_version: 3.1.4
|
147
153
|
signing_key:
|
148
154
|
specification_version: 4
|
149
155
|
summary: Localize your app with YAML or GetText. Synchronize with your translators
|