i18n-docs 0.0.9 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +4 -0
- data/.github/workflows/ci.yml +21 -0
- data/.gitignore +6 -1
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +50 -0
- data/Gemfile +8 -2
- data/README.md +87 -7
- data/Rakefile +22 -11
- data/i18n-docs.gemspec +13 -9
- data/lib/i18n-docs.rb +6 -13
- data/lib/{localch_i18n → i18n_docs}/csv_to_yaml.rb +26 -21
- data/lib/{localch_i18n → i18n_docs}/missing_keys_finder.rb +18 -21
- data/lib/{localch_i18n → i18n_docs}/translation_file_export.rb +18 -26
- data/lib/{localch_i18n → i18n_docs}/translations.rb +10 -10
- data/lib/i18n_docs/version.rb +3 -0
- data/lib/tasks/store_translations.rake +22 -31
- data/test/fixtures/config.yml +1 -1
- data/test/fixtures/error.csv +3 -0
- data/test/test_helper.rb +5 -7
- data/test/unit/csv_to_yaml_test.rb +41 -24
- data/test/unit/translation_file_export_test.rb +16 -20
- data/test/unit/translations_test.rb +16 -16
- metadata +47 -15
- data/lib/localch_i18n/version.rb +0 -3
- data/tasks/test.rake +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 856b480dbfe843f57e65141e6c217c80ee30944c95131d82eec949e700b19517
|
4
|
+
data.tar.gz: d572f840dda955f15e2f8794d517e5226f22527779d68a7b3b83a3133faa3c05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 218816a28ac21a8063ebcc84230d88d50ea30ee599b1c2d4292bd58e583cee9448b7ac8a51817151f5f3b856ab55b07393ebaa2ef6cbd39dc468260a0b32c769
|
7
|
+
data.tar.gz: 361d4054384bc505de49f635fd1532c65a396702a883de438023ef83dbb72e5dc82740f82c772ea9871d34f908ab8c9f706df9fbc9b25ab1cf1fbc39299affc5
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
|
9
|
+
strategy:
|
10
|
+
matrix:
|
11
|
+
ruby-version: [head, 3.0, 2.7, 2.6, 2.5, 2.4, 2.3]
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby-version }}
|
19
|
+
bundler-cache: true
|
20
|
+
- name: Run tests
|
21
|
+
run: bundle exec rake test
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-07-11 14:36:42 +0200 using RuboCop version 0.48.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 8
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 30
|
12
|
+
|
13
|
+
# Offense count: 1
|
14
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
15
|
+
Metrics/BlockLength:
|
16
|
+
Max: 37
|
17
|
+
|
18
|
+
# Offense count: 4
|
19
|
+
# Configuration parameters: CountComments.
|
20
|
+
Metrics/MethodLength:
|
21
|
+
Max: 26
|
22
|
+
|
23
|
+
# Offense count: 1
|
24
|
+
Metrics/PerceivedComplexity:
|
25
|
+
Max: 8
|
26
|
+
|
27
|
+
# Offense count: 1
|
28
|
+
Style/AsciiComments:
|
29
|
+
Exclude:
|
30
|
+
- 'lib/i18n_docs/missing_keys_finder.rb'
|
31
|
+
|
32
|
+
# Offense count: 1
|
33
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
34
|
+
# SupportedStyles: nested, compact
|
35
|
+
Style/ClassAndModuleChildren:
|
36
|
+
Exclude:
|
37
|
+
- 'lib/i18n-docs.rb'
|
38
|
+
|
39
|
+
# Offense count: 1
|
40
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
41
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
42
|
+
Style/FileName:
|
43
|
+
Exclude:
|
44
|
+
- 'lib/i18n-docs.rb'
|
45
|
+
|
46
|
+
# Offense count: 1
|
47
|
+
# Configuration parameters: MinBodyLength.
|
48
|
+
Style/GuardClause:
|
49
|
+
Exclude:
|
50
|
+
- 'lib/i18n_docs/csv_to_yaml.rb'
|
data/Gemfile
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
#
|
3
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
4
|
+
# development dependencies will be added by default to the :development group.
|
4
5
|
gemspec
|
6
|
+
|
7
|
+
# Declare any dependencies that are still in development here instead of in
|
8
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
9
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
10
|
+
# your gem to rubygems.org.
|
data/README.md
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
# i18n-docs
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/renuo/i18n-docs.svg?branch=master)](https://travis-ci.org/renuo/i18n-docs)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/renuo/i18n-docs/badges/gpa.svg)](https://codeclimate.com/github/renuo/i18n-docs)
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/renuo/i18n-docs/badges/coverage.svg)](https://codeclimate.com/github/renuo/i18n-docs/coverage)
|
6
|
+
[![Issue Count](https://codeclimate.com/github/renuo/i18n-docs/badges/issue_count.svg)](https://codeclimate.com/github/renuo/i18n-docs)
|
7
|
+
[![Dependency Status](https://gemnasium.com/badges/github.com/renuo/i18n-docs.svg)](https://gemnasium.com/github.com/renuo/i18n-docs)
|
8
|
+
|
3
9
|
**i18n-docs** is a ruby gem that helps you to keep translations stored in Google Docs. This makes it easier for translators and project members to coordinate changes and updates. In addition, the standard features of Google Docs are super handy for this process: revision tracking, authorization, publishing, etc.
|
4
10
|
|
5
11
|
Although we use it with Google Docs, it could be used with any CSV file.
|
6
12
|
|
7
13
|
*this gem is currently in use and tested with Rails 3.1. It probably works with other 3.x versions, but probably not 2.x at the moment.*
|
8
14
|
|
9
|
-
## Features
|
15
|
+
## Features
|
10
16
|
|
11
17
|
* download translations from multiple Google spreadsheets and store to YAML files
|
12
18
|
* import/export YAML files with a Google Spreadsheet
|
13
19
|
* check YAML files for missing translations (`rake i18n:find_missing_keys`)
|
14
20
|
|
21
|
+
## Tests
|
22
|
+
|
23
|
+
Verify the quality of this gem by checking out this repo and running:
|
24
|
+
|
25
|
+
bundle install
|
26
|
+
rake test
|
27
|
+
|
15
28
|
## Usage
|
16
29
|
|
17
30
|
### Configuration
|
18
31
|
|
19
|
-
Add the GEM to your
|
32
|
+
Add the GEM to your project:
|
20
33
|
|
21
34
|
gem 'i18n-docs'
|
22
35
|
|
@@ -27,6 +40,8 @@ Create a configuration file in `config/translations.yml`:
|
|
27
40
|
forms.yml: "https://docs.google.com/spreadsheet/pub?key=0Ap...XveWc&single=true&gid=0&output=csv"
|
28
41
|
... etc ...
|
29
42
|
|
43
|
+
#### Rails
|
44
|
+
|
30
45
|
Finally, let Rails know what locales you will be using. Add this to `config/application.rb`:
|
31
46
|
|
32
47
|
module Web
|
@@ -40,6 +55,41 @@ Finally, let Rails know what locales you will be using. Add this to `config/appl
|
|
40
55
|
|
41
56
|
This defines which languages and translation files to import from a Google Spreadsheet. The content of the Spreadsheet URL is stored to a file called e.g. `example1.yml` within folders `config/locales/en` and all other detected locales.
|
42
57
|
|
58
|
+
#### Non Rails
|
59
|
+
|
60
|
+
Load rake tasks in your `Rakefile`:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
require 'i18n-docs'
|
64
|
+
|
65
|
+
spec = Gem::Specification.find_by_name 'i18n-docs'
|
66
|
+
load "#{spec.gem_dir}/lib/tasks/store_translations.rake"
|
67
|
+
```
|
68
|
+
|
69
|
+
Create `environment` task in your `Rakefile`:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
task :environment do
|
73
|
+
...
|
74
|
+
end
|
75
|
+
|
76
|
+
```
|
77
|
+
|
78
|
+
The minimal scope of this task is to set up `I18n.available_locales`.
|
79
|
+
|
80
|
+
Translations will be stored under `config/locales` in project root directory.
|
81
|
+
Don't forget to setup `I18n` accordingly:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
I18n.load_path = Dir[File.join(MyProject.root, 'config', 'locales', '**', '*.yml')]
|
85
|
+
```
|
86
|
+
|
87
|
+
And to load them:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
I18n.backend.load_translations
|
91
|
+
```
|
92
|
+
|
43
93
|
### Rake Tasks
|
44
94
|
|
45
95
|
Following Rake tasks are added by the GEM to your Rails project:
|
@@ -62,6 +112,24 @@ Following Rake tasks are added by the GEM to your Rails project:
|
|
62
112
|
![screenshot](http://dl.dropbox.com/u/385855/Screenshots/oom_.png)
|
63
113
|
* From now on you should only update translations in Google Docs and run `rake i18n:import_translations` in the application to get changes. You can also export your
|
64
114
|
|
115
|
+
|
116
|
+
## Configuraiton
|
117
|
+
|
118
|
+
You can include a set of substitions for preprocessing the CSV after downloading it and before parsing it. Here is an example that replaces non-breaking spaces with normal ones.
|
119
|
+
|
120
|
+
files:
|
121
|
+
navigation.yml: "https://docs.google.com/spreadsheet/pub?key=ab43...34f3&single=true&gid=0&output=csv"
|
122
|
+
|
123
|
+
substitutions:
|
124
|
+
- from: "\u00A0"
|
125
|
+
to: ' '
|
126
|
+
|
127
|
+
|
128
|
+
## Error Handling
|
129
|
+
|
130
|
+
I case of the error `OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed` when running `rake i18n:import_translations`
|
131
|
+
Follow this: http://stackoverflow.com/questions/12562697/opensslsslsslerror-ssl-connect-returned-1-errno-0-state-sslv3-read-server-ce?answertab=active#tab-top
|
132
|
+
|
65
133
|
## Todo
|
66
134
|
|
67
135
|
*Pull requests welcome!*
|
@@ -73,7 +141,21 @@ Following Rake tasks are added by the GEM to your Rails project:
|
|
73
141
|
|
74
142
|
## CHANGELOG
|
75
143
|
|
76
|
-
|
144
|
+
### 0.1.1
|
145
|
+
|
146
|
+
* add `substitutions` config
|
147
|
+
|
148
|
+
|
149
|
+
### 0.1.0
|
150
|
+
|
151
|
+
* usable outside of rails
|
152
|
+
|
153
|
+
### 0.0.10
|
154
|
+
|
155
|
+
* rename module to be inline with the gem-name
|
156
|
+
* various cleanups
|
157
|
+
|
158
|
+
### 0.0.9
|
77
159
|
|
78
160
|
* add version.rb
|
79
161
|
* content downloaded is forced to UTF-8
|
@@ -82,10 +164,9 @@ Following Rake tasks are added by the GEM to your Rails project:
|
|
82
164
|
* create tmp directory if it does not exist
|
83
165
|
* strip spaces from keys
|
84
166
|
|
85
|
-
|
167
|
+
### 0.0.7
|
86
168
|
|
87
|
-
*
|
88
|
-
* this version has been YANKED
|
169
|
+
* YANKED from rubygems.org, sorry
|
89
170
|
|
90
171
|
### 0.0.7
|
91
172
|
|
@@ -107,4 +188,3 @@ Following Rake tasks are added by the GEM to your Rails project:
|
|
107
188
|
### Credits/License
|
108
189
|
|
109
190
|
This gem is sponsored by [local.ch](http://www.local.ch/). It is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License). If you're a ruby developer and want to work with us in Switzerland, please check out our [jobs page](http://local-ch.github.com/).
|
110
|
-
|
data/Rakefile
CHANGED
@@ -1,17 +1,28 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
1
|
begin
|
4
|
-
|
5
|
-
rescue
|
6
|
-
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
9
5
|
end
|
10
6
|
|
11
|
-
require 'bundler/gem_tasks'
|
12
7
|
require 'i18n-docs'
|
8
|
+
require 'rdoc/task'
|
9
|
+
require 'rake/testtask'
|
13
10
|
|
14
|
-
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'i18n-docs'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
Bundler::GemHelper.install_tasks
|
20
|
+
|
21
|
+
# Test::Unit Tests
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
15
27
|
|
16
|
-
|
17
|
-
Dir.glob('tasks/**/*.rake').each { |r| Rake.application.add_import r }
|
28
|
+
task default: [:test]
|
data/i18n-docs.gemspec
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
2
|
# Maintain your gem's version:
|
3
|
-
require '
|
3
|
+
require 'i18n_docs/version'
|
4
4
|
|
5
5
|
# encoding: utf-8
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'i18n-docs'
|
8
|
-
s.version =
|
8
|
+
s.version = I18nDocs::VERSION
|
9
9
|
s.date = '2013-05-10'
|
10
|
-
s.summary =
|
11
|
-
s.description =
|
12
|
-
|
13
|
-
|
10
|
+
s.summary = 'Maintain translations in Google Docs and export them to your Rails project.'
|
11
|
+
s.description = 'GEM providing helper scripts to manage i18n translations in Google Docs. '\
|
12
|
+
'Features: check YAML files for missing translations; export YAML files to CSV; '\
|
13
|
+
'download translations from multiple Google spreadsheets and store to YAML files'
|
14
|
+
s.authors = ['Georg Kunz', 'Ivan Jovanovic', 'Jeremy Seitz', 'Eduard Schäli', 'Robin Wunderlin',
|
15
|
+
'Esteban Pastorino', 'Krzysztof Sakwerda']
|
16
|
+
s.email = 'eduard.schaeli@localsearch.ch'
|
14
17
|
s.files = `git ls-files`.split("\n")
|
15
18
|
s.homepage = 'https://github.com/local-ch/i18n-docs'
|
16
19
|
|
@@ -18,6 +21,7 @@ Gem::Specification.new do |s|
|
|
18
21
|
s.add_dependency('rake')
|
19
22
|
|
20
23
|
s.add_development_dependency('mocha', '~> 0.13.3')
|
21
|
-
s.add_development_dependency('
|
22
|
-
|
24
|
+
s.add_development_dependency('test-unit', '~> 3.1.7')
|
25
|
+
s.add_development_dependency('simplecov', '~> 0.16.1')
|
26
|
+
s.add_development_dependency('rubocop', '~> 0.48.0')
|
23
27
|
end
|
data/lib/i18n-docs.rb
CHANGED
@@ -1,22 +1,15 @@
|
|
1
|
-
# require 'rake'
|
2
|
-
|
3
|
-
# load rake tasks in case GEM is included within rails project
|
4
|
-
|
5
1
|
require 'csv'
|
6
2
|
require 'yaml'
|
7
3
|
require 'open-uri'
|
8
|
-
require '
|
9
|
-
require '
|
10
|
-
require '
|
11
|
-
require '
|
12
|
-
|
13
|
-
|
4
|
+
require 'i18n_docs/missing_keys_finder'
|
5
|
+
require 'i18n_docs/csv_to_yaml'
|
6
|
+
require 'i18n_docs/translations'
|
7
|
+
require 'i18n_docs/translation_file_export'
|
14
8
|
|
15
9
|
if defined?(Rails)
|
16
|
-
class
|
10
|
+
class I18nDocs::Railtie < Rails::Railtie
|
17
11
|
rake_tasks do
|
18
|
-
Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
|
12
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f }
|
19
13
|
end
|
20
14
|
end
|
21
15
|
end
|
22
|
-
|
@@ -1,9 +1,11 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module I18nDocs
|
3
2
|
class CsvToYaml
|
4
|
-
|
5
3
|
attr_reader :input_file, :output_file, :locales, :translations
|
6
4
|
|
5
|
+
def self.root_path
|
6
|
+
@root_path ||= defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd)
|
7
|
+
end
|
8
|
+
|
7
9
|
def initialize(input_file, output_file, locales = [])
|
8
10
|
@input_file = input_file
|
9
11
|
@output_file = File.basename(output_file)
|
@@ -16,24 +18,19 @@ module LocalchI18n
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
21
|
def write_files
|
21
22
|
@locales.each do |locale|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
output_file_path = "#{locale}_#{@output_file}"
|
27
|
-
end
|
23
|
+
output_file_path = self.class.root_path.join('config', 'locales', locale, @output_file)
|
24
|
+
FileUtils.mkdir_p File.dirname(output_file_path)
|
25
|
+
|
28
26
|
File.open(output_file_path, 'w') do |file|
|
29
|
-
final_translation_hash = {locale => @translations[locale]}
|
30
|
-
file.puts YAML
|
27
|
+
final_translation_hash = { locale => @translations[locale] }
|
28
|
+
file.puts YAML.dump(final_translation_hash)
|
31
29
|
end
|
32
30
|
puts "File '#{@output_file}' for language '#{locale}' written to disc (#{output_file_path})"
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
36
|
-
|
37
34
|
def process
|
38
35
|
CSV.foreach(@input_file, headers: true) do |row|
|
39
36
|
process_row(row.to_hash)
|
@@ -46,14 +43,15 @@ module LocalchI18n
|
|
46
43
|
|
47
44
|
key_elements = key.split('.')
|
48
45
|
@locales.each do |locale|
|
49
|
-
|
46
|
+
unless row_hash.key?(locale)
|
47
|
+
raise "Locale missing for key #{key}! (locales in app: #{@locales} / locales in file: #{row_hash.keys})"
|
48
|
+
end
|
50
49
|
store_translation(key_elements, locale, row_hash[locale])
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
54
|
-
|
55
53
|
def store_translation(keys, locale, value)
|
56
|
-
return nil if value.nil?
|
54
|
+
return nil if value.nil? # we don't store keys that don't have a valid value
|
57
55
|
# Google Spreadsheet does not export empty strings and therefore we use '_' as a replacement char.
|
58
56
|
value = '' if value == '_'
|
59
57
|
|
@@ -61,15 +59,22 @@ module LocalchI18n
|
|
61
59
|
tree = keys[0...-1]
|
62
60
|
leaf = keys.last
|
63
61
|
data_hash = tree.inject(@translations[locale]) do |memo, k|
|
64
|
-
if memo.
|
65
|
-
memo
|
62
|
+
if memo.is_a? Hash
|
63
|
+
if memo.key?(k)
|
64
|
+
memo[k]
|
65
|
+
else
|
66
|
+
memo[k] = {}
|
67
|
+
end
|
66
68
|
else
|
67
|
-
|
69
|
+
raise "Error around key '#{keys.join '.'}': Expected #{memo.inspect} to be a Hash"
|
68
70
|
end
|
69
71
|
end
|
72
|
+
|
73
|
+
if data_hash.is_a? String
|
74
|
+
raise "Error around key '#{keys.join '.'}': Expected #{data_hash.inspect} to be a Hash"
|
75
|
+
end
|
76
|
+
|
70
77
|
data_hash[leaf] = value
|
71
78
|
end
|
72
|
-
|
73
79
|
end
|
74
|
-
|
75
80
|
end
|
@@ -1,15 +1,14 @@
|
|
1
|
-
|
2
|
-
module LocalchI18n
|
1
|
+
module I18nDocs
|
3
2
|
class MissingKeysFinder
|
4
3
|
def initialize(backend)
|
5
4
|
@backend = backend
|
6
|
-
|
7
|
-
|
5
|
+
load_config
|
6
|
+
load_translations
|
8
7
|
end
|
9
8
|
|
10
9
|
# Returns an array with all keys from all locales
|
11
10
|
def all_keys
|
12
|
-
I18n.backend.send(:translations).collect do |
|
11
|
+
I18n.backend.send(:translations).collect do |_check_locale, translations|
|
13
12
|
collect_keys([], translations).sort
|
14
13
|
end.flatten.uniq
|
15
14
|
end
|
@@ -20,12 +19,10 @@ module LocalchI18n
|
|
20
19
|
|
21
20
|
missing_keys = {}
|
22
21
|
all_keys.each do |key|
|
23
|
-
|
24
22
|
I18n.available_locales.each do |locale|
|
25
|
-
|
26
23
|
skip = false
|
27
24
|
ls = locale.to_s
|
28
|
-
|
25
|
+
unless @yaml[ls].nil?
|
29
26
|
@yaml[ls].each do |re|
|
30
27
|
if key.match(re)
|
31
28
|
skip = true
|
@@ -45,24 +42,26 @@ module LocalchI18n
|
|
45
42
|
end
|
46
43
|
|
47
44
|
output_missing_keys(missing_keys)
|
48
|
-
|
45
|
+
missing_keys
|
49
46
|
end
|
50
47
|
|
48
|
+
# rubocop:disable Metrics/LineLength
|
51
49
|
def output_available_locales
|
52
50
|
puts "#{I18n.available_locales.size} #{I18n.available_locales.size == 1 ? 'locale' : 'locales'} available: #{I18n.available_locales.join(', ')}"
|
53
51
|
end
|
54
52
|
|
55
53
|
def output_missing_keys(missing_keys)
|
56
|
-
if missing_keys.
|
54
|
+
if missing_keys.any?
|
57
55
|
puts "#{missing_keys.size} #{missing_keys.size == 1 ? 'key is missing' : 'keys are missing'} from one or more locales:"
|
58
56
|
missing_keys.keys.sort.each do |key|
|
59
57
|
puts "'#{key}': Missing from #{missing_keys[key].collect(&:inspect).join(', ')}"
|
60
58
|
end
|
61
59
|
puts "\nERROR: #{missing_keys.size} #{missing_keys.size == 1 ? 'key is missing' : 'keys are missing'} from one or more locales."
|
62
60
|
else
|
63
|
-
puts
|
61
|
+
puts 'No keys are missing'
|
64
62
|
end
|
65
63
|
end
|
64
|
+
# rubocop:enable Metrics/LineLength
|
66
65
|
|
67
66
|
def output_unique_key_stats(keys)
|
68
67
|
number_of_keys = keys.size
|
@@ -71,21 +70,21 @@ module LocalchI18n
|
|
71
70
|
|
72
71
|
def collect_keys(scope, translations)
|
73
72
|
full_keys = []
|
74
|
-
translations.to_a.each do |key,
|
73
|
+
translations.to_a.each do |key, translation|
|
75
74
|
new_scope = scope.dup << key
|
76
|
-
if
|
77
|
-
full_keys += collect_keys(new_scope,
|
75
|
+
if translation.is_a?(Hash)
|
76
|
+
full_keys += collect_keys(new_scope, translation)
|
78
77
|
else
|
79
78
|
full_keys << new_scope.join('.')
|
80
79
|
end
|
81
80
|
end
|
82
|
-
|
81
|
+
full_keys
|
83
82
|
end
|
84
83
|
|
85
84
|
# Returns true if key exists in the given locale
|
86
85
|
def key_exists?(key, locale)
|
87
86
|
I18n.locale = locale
|
88
|
-
I18n.translate(key, :
|
87
|
+
I18n.translate(key, raise: true)
|
89
88
|
return true
|
90
89
|
rescue I18n::MissingInterpolationArgument
|
91
90
|
return true
|
@@ -102,11 +101,9 @@ module LocalchI18n
|
|
102
101
|
@yaml = {}
|
103
102
|
begin
|
104
103
|
@yaml = YAML.load_file(File.join(Rails.root, 'config', 'ignore_missing_i18n_keys.yml'))
|
105
|
-
rescue
|
106
|
-
STDERR.puts
|
104
|
+
rescue
|
105
|
+
STDERR.puts 'No ignore_missing_keys.yml config file.'
|
107
106
|
end
|
108
|
-
|
109
107
|
end
|
110
|
-
|
111
108
|
end
|
112
|
-
end
|
109
|
+
end
|
@@ -1,33 +1,30 @@
|
|
1
|
-
module
|
1
|
+
module I18nDocs
|
2
2
|
class TranslationFileExport
|
3
|
-
|
4
3
|
attr_accessor :translations
|
5
|
-
|
4
|
+
|
6
5
|
def initialize(source_dir, source_file, output_dir, locales)
|
7
6
|
@source_dir = source_dir
|
8
7
|
@source_file = source_file
|
9
|
-
|
8
|
+
|
10
9
|
@output_file = File.join(output_dir, source_file.gsub('.yml', '.csv'))
|
11
|
-
@locales = locales.map
|
12
|
-
|
10
|
+
@locales = locales.map(&:to_s)
|
11
|
+
|
13
12
|
@translations = {}
|
14
13
|
end
|
15
|
-
|
16
|
-
|
14
|
+
|
17
15
|
def export
|
18
16
|
load_translations
|
19
17
|
write_to_csv
|
20
18
|
end
|
21
|
-
|
22
|
-
|
19
|
+
|
23
20
|
def write_to_csv
|
24
21
|
main_locale = @locales.include?('en') ? 'en' : @locales.first
|
25
|
-
|
22
|
+
|
26
23
|
puts " #{@source_file}: write CSV to '#{@output_file}' \n\n"
|
27
|
-
|
28
|
-
CSV.open(@output_file,
|
29
|
-
csv << ([
|
30
|
-
|
24
|
+
|
25
|
+
CSV.open(@output_file, 'wb') do |csv|
|
26
|
+
csv << (['key'] + @locales)
|
27
|
+
|
31
28
|
@translations[main_locale].keys.each do |key|
|
32
29
|
values = @locales.map do |locale|
|
33
30
|
@translations[locale][key]
|
@@ -35,30 +32,27 @@ module LocalchI18n
|
|
35
32
|
csv << values.unshift(key)
|
36
33
|
end
|
37
34
|
end
|
38
|
-
|
39
35
|
end
|
40
|
-
|
41
|
-
|
36
|
+
|
42
37
|
def load_translations
|
43
38
|
@locales.each do |locale|
|
44
39
|
translation_hash = load_language(locale)
|
45
40
|
@translations[locale] = flatten_translations_hash(translation_hash)
|
46
41
|
end
|
47
42
|
end
|
48
|
-
|
43
|
+
|
49
44
|
def load_language(locale)
|
50
|
-
|
51
45
|
puts " #{@source_file}: load translations for '#{locale}'"
|
52
|
-
|
46
|
+
|
53
47
|
input_file = File.join(@source_dir, locale, @source_file)
|
54
48
|
translations = {}
|
55
|
-
translations = YAML.load_file(input_file) if File.
|
49
|
+
translations = YAML.load_file(input_file) if File.exist?(input_file)
|
56
50
|
translations[locale]
|
57
51
|
end
|
58
|
-
|
52
|
+
|
59
53
|
def flatten_translations_hash(translations, parent_key = [])
|
60
54
|
flat_hash = {}
|
61
|
-
|
55
|
+
|
62
56
|
translations.each do |key, t|
|
63
57
|
current_key = parent_key.dup << key
|
64
58
|
if t.is_a?(Hash)
|
@@ -71,7 +65,5 @@ module LocalchI18n
|
|
71
65
|
end
|
72
66
|
flat_hash
|
73
67
|
end
|
74
|
-
|
75
68
|
end
|
76
|
-
|
77
69
|
end
|