i18n-docs 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5dfaf572b4a18ef1c85ae6641dba030ca833fc2f
4
- data.tar.gz: 85391361b7c3c7f2eea154a7aa5bed34b15e0ccb
2
+ SHA256:
3
+ metadata.gz: 856b480dbfe843f57e65141e6c217c80ee30944c95131d82eec949e700b19517
4
+ data.tar.gz: d572f840dda955f15e2f8794d517e5226f22527779d68a7b3b83a3133faa3c05
5
5
  SHA512:
6
- metadata.gz: 90bb038ed0f6651347019398af8373e8f1daf84007e70531e3aecb7a6c5f6952f9f7850078253cad119ba56cf4b92f6447e58290230ce6b218df8e079753fe32
7
- data.tar.gz: 388126fd79d675b78b541c99da04c0b384eb10ad07562d59e0676320535c50e0d320fe5a530898922e76c398d9fc9086ee88570ff5900eadd19123e9c58941e5
6
+ metadata.gz: 218816a28ac21a8063ebcc84230d88d50ea30ee599b1c2d4292bd58e583cee9448b7ac8a51817151f5f3b856ab55b07393ebaa2ef6cbd39dc468260a0b32c769
7
+ data.tar.gz: 361d4054384bc505de49f635fd1532c65a396702a883de438023ef83dbb72e5dc82740f82c772ea9871d34f908ab8c9f706df9fbc9b25ab1cf1fbc39299affc5
data/.codeclimate.yml ADDED
@@ -0,0 +1,4 @@
1
+ engines:
2
+ rubocop:
3
+ enabled: true
4
+ channel: rubocop-0-48
@@ -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
@@ -11,3 +11,4 @@ tmp/*
11
11
  .ruby-version
12
12
  .ruby-gemset
13
13
  rdoc/
14
+ coverage/
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Metrics/LineLength:
4
+ Max: 120
5
+
6
+ Style/Documentation:
7
+ Enabled: false
8
+
9
+ Metrics/ClassLength:
10
+ Exclude:
11
+ - 'test/**/*_test.rb'
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,4 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Bundler will treat runtime dependencies like base dependencies, and
4
4
  # development dependencies will be added by default to the :development group.
data/README.md CHANGED
@@ -1,17 +1,30 @@
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
@@ -99,6 +112,19 @@ Following Rake tasks are added by the GEM to your Rails project:
99
112
  ![screenshot](http://dl.dropbox.com/u/385855/Screenshots/oom_.png)
100
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
101
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
+
102
128
  ## Error Handling
103
129
 
104
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`
@@ -115,6 +141,15 @@ Follow this: http://stackoverflow.com/questions/12562697/opensslsslsslerror-ssl-
115
141
 
116
142
  ## CHANGELOG
117
143
 
144
+ ### 0.1.1
145
+
146
+ * add `substitutions` config
147
+
148
+
149
+ ### 0.1.0
150
+
151
+ * usable outside of rails
152
+
118
153
  ### 0.0.10
119
154
 
120
155
  * rename module to be inline with the gem-name
data/Rakefile CHANGED
@@ -25,4 +25,4 @@ Rake::TestTask.new(:test) do |test|
25
25
  test.verbose = true
26
26
  end
27
27
 
28
- task :default => [:test]
28
+ task default: [:test]
data/i18n-docs.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- $:.push File.expand_path("../lib", __FILE__)
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
2
  # Maintain your gem's version:
3
3
  require 'i18n_docs/version'
4
4
 
@@ -7,9 +7,12 @@ Gem::Specification.new do |s|
7
7
  s.name = 'i18n-docs'
8
8
  s.version = I18nDocs::VERSION
9
9
  s.date = '2013-05-10'
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. Features: check YAML files for missing translations; export YAML files to CSV; download translations from multiple Google spreadsheets and store to YAML files"
12
- s.authors = ["Georg Kunz", "Ivan Jovanovic", "Jeremy Seitz", "Eduard Schäli", "Robin Wunderlin", "Esteban Pastorino", "Krzysztof Sakwerda"]
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']
13
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'
@@ -19,4 +22,6 @@ Gem::Specification.new do |s|
19
22
 
20
23
  s.add_development_dependency('mocha', '~> 0.13.3')
21
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')
22
27
  end
data/lib/i18n-docs.rb CHANGED
@@ -9,8 +9,7 @@ require 'i18n_docs/translation_file_export'
9
9
  if defined?(Rails)
10
10
  class I18nDocs::Railtie < Rails::Railtie
11
11
  rake_tasks do
12
- 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 }
13
13
  end
14
14
  end
15
15
  end
16
-
@@ -1,7 +1,5 @@
1
1
  module I18nDocs
2
-
3
2
  class CsvToYaml
4
-
5
3
  attr_reader :input_file, :output_file, :locales, :translations
6
4
 
7
5
  def self.root_path
@@ -20,21 +18,19 @@ module I18nDocs
20
18
  end
21
19
  end
22
20
 
23
-
24
21
  def write_files
25
22
  @locales.each do |locale|
26
23
  output_file_path = self.class.root_path.join('config', 'locales', locale, @output_file)
27
24
  FileUtils.mkdir_p File.dirname(output_file_path)
28
25
 
29
26
  File.open(output_file_path, 'w') do |file|
30
- final_translation_hash = {locale => @translations[locale]}
31
- file.puts YAML::dump(final_translation_hash)
27
+ final_translation_hash = { locale => @translations[locale] }
28
+ file.puts YAML.dump(final_translation_hash)
32
29
  end
33
30
  puts "File '#{@output_file}' for language '#{locale}' written to disc (#{output_file_path})"
34
31
  end
35
32
  end
36
33
 
37
-
38
34
  def process
39
35
  CSV.foreach(@input_file, headers: true) do |row|
40
36
  process_row(row.to_hash)
@@ -47,14 +43,15 @@ module I18nDocs
47
43
 
48
44
  key_elements = key.split('.')
49
45
  @locales.each do |locale|
50
- raise "Locale missing for key #{key}! (locales in app: #{@locales} / locales in file: #{row_hash.keys.to_s})" if !row_hash.has_key?(locale)
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
51
49
  store_translation(key_elements, locale, row_hash[locale])
52
50
  end
53
51
  end
54
52
 
55
-
56
53
  def store_translation(keys, locale, value)
57
- return nil if value.nil? # we don't store keys that don't have a valid value
54
+ return nil if value.nil? # we don't store keys that don't have a valid value
58
55
  # Google Spreadsheet does not export empty strings and therefore we use '_' as a replacement char.
59
56
  value = '' if value == '_'
60
57
 
@@ -63,7 +60,7 @@ module I18nDocs
63
60
  leaf = keys.last
64
61
  data_hash = tree.inject(@translations[locale]) do |memo, k|
65
62
  if memo.is_a? Hash
66
- if memo.has_key?(k)
63
+ if memo.key?(k)
67
64
  memo[k]
68
65
  else
69
66
  memo[k] = {}
@@ -79,7 +76,5 @@ module I18nDocs
79
76
 
80
77
  data_hash[leaf] = value
81
78
  end
82
-
83
79
  end
84
-
85
80
  end
@@ -1,15 +1,14 @@
1
-
2
1
  module I18nDocs
3
2
  class MissingKeysFinder
4
3
  def initialize(backend)
5
4
  @backend = backend
6
- self.load_config
7
- self.load_translations
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 |check_locale, translations|
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 I18nDocs
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
- if !@yaml[ls].nil?
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 I18nDocs
45
42
  end
46
43
 
47
44
  output_missing_keys(missing_keys)
48
- return missing_keys
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.size > 0
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 "No keys are missing"
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
@@ -79,13 +78,13 @@ module I18nDocs
79
78
  full_keys << new_scope.join('.')
80
79
  end
81
80
  end
82
- return full_keys
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, :raise => true)
87
+ I18n.translate(key, raise: true)
89
88
  return true
90
89
  rescue I18n::MissingInterpolationArgument
91
90
  return true
@@ -103,10 +102,8 @@ module I18nDocs
103
102
  begin
104
103
  @yaml = YAML.load_file(File.join(Rails.root, 'config', 'ignore_missing_i18n_keys.yml'))
105
104
  rescue
106
- STDERR.puts "No ignore_missing_keys.yml config file."
105
+ STDERR.puts 'No ignore_missing_keys.yml config file.'
107
106
  end
108
-
109
107
  end
110
-
111
108
  end
112
109
  end
@@ -1,6 +1,5 @@
1
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)
@@ -8,25 +7,23 @@ module I18nDocs
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 {|l| l.to_s }
10
+ @locales = locales.map(&:to_s)
12
11
 
13
12
  @translations = {}
14
13
  end
15
14
 
16
-
17
15
  def export
18
16
  load_translations
19
17
  write_to_csv
20
18
  end
21
19
 
22
-
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
24
 
28
- CSV.open(@output_file, "wb") do |csv|
29
- csv << (["key"] + @locales)
25
+ CSV.open(@output_file, 'wb') do |csv|
26
+ csv << (['key'] + @locales)
30
27
 
31
28
  @translations[main_locale].keys.each do |key|
32
29
  values = @locales.map do |locale|
@@ -35,10 +32,8 @@ module I18nDocs
35
32
  csv << values.unshift(key)
36
33
  end
37
34
  end
38
-
39
35
  end
40
36
 
41
-
42
37
  def load_translations
43
38
  @locales.each do |locale|
44
39
  translation_hash = load_language(locale)
@@ -47,7 +42,6 @@ module I18nDocs
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)
@@ -71,7 +65,5 @@ module I18nDocs
71
65
  end
72
66
  flat_hash
73
67
  end
74
-
75
68
  end
76
-
77
69
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # Order of method calls
3
2
  # download_files
4
3
  # store_translations
@@ -6,7 +5,6 @@
6
5
  #
7
6
  module I18nDocs
8
7
  class Translations
9
-
10
8
  attr_accessor :locales, :tmp_folder, :config_file, :csv_files
11
9
 
12
10
  def initialize(config_file = nil, tmp_folder = nil)
@@ -32,8 +30,8 @@ module I18nDocs
32
30
  def download_files
33
31
  files = @settings['files']
34
32
  files.each do |target_file, url|
35
- #ensure .yml filename
36
- target_file = target_file + ".yml" if target_file !~ /\.yml$/
33
+ # ensure .yml filename
34
+ target_file += '.yml' if target_file !~ /\.yml$/
37
35
  # download file to tmp directory
38
36
  tmp_file = File.basename(target_file).gsub('.yml', '.csv')
39
37
  tmp_file = File.join(@tmp_folder, tmp_file)
@@ -54,7 +52,7 @@ module I18nDocs
54
52
 
55
53
  def clean_up
56
54
  # remove all tmp files
57
- @csv_files.each do |target_file, csv_file|
55
+ @csv_files.each do |_target_file, csv_file|
58
56
  File.unlink(csv_file)
59
57
  end
60
58
  end
@@ -62,10 +60,14 @@ module I18nDocs
62
60
  def download(url, destination_file)
63
61
  puts "Download '#{url}' to '#{destination_file}'"
64
62
  doc_data = open(url).read.force_encoding('UTF-8')
63
+ if (subs = @settings['substitutions'])
64
+ subs.each do |sub|
65
+ doc_data.gsub! sub['from'], sub['to']
66
+ end
67
+ end
65
68
  File.open(destination_file, 'w') do |dst|
66
69
  dst.write(doc_data)
67
70
  end
68
71
  end
69
-
70
72
  end
71
73
  end
@@ -1,3 +1,3 @@
1
1
  module I18nDocs
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'.freeze
3
3
  end
@@ -1,17 +1,15 @@
1
1
 
2
2
  namespace :i18n do
3
-
4
- desc "Find and list translation keys that do not exist in all locales"
5
- task :missing_keys => :environment do
3
+ desc 'Find and list translation keys that do not exist in all locales'
4
+ task missing_keys: :environment do
6
5
  finder = I18nDocs::MissingKeysFinder.new(I18n.backend)
7
6
  finder.find_missing_keys
8
7
  end
9
8
 
10
- desc "Download translations from Google Spreadsheet and save them to YAML files."
11
- task :import_translations => :environment do
12
-
9
+ desc 'Download translations from Google Spreadsheet and save them to YAML files.'
10
+ task import_translations: :environment do
13
11
  config_file = I18nDocs::CsvToYaml.root_path.join('config', 'translations.yml')
14
- raise "No config file 'config/translations.yml' found." if !File.exist?(config_file)
12
+ raise "No config file 'config/translations.yml' found." unless File.exist?(config_file)
15
13
 
16
14
  tmp_dir = I18nDocs::CsvToYaml.root_path.join('tmp')
17
15
  Dir.mkdir(tmp_dir) unless Dir.exist?(tmp_dir)
@@ -20,24 +18,23 @@ namespace :i18n do
20
18
  translations.download_files
21
19
  translations.store_translations
22
20
  translations.clean_up
23
-
24
21
  end
25
22
 
26
- desc "Export all language files to CSV files (only files contained in en folder are considered)"
27
- task :export_translations => :environment do
23
+ desc 'Export all language files to CSV files (only files contained in en folder are considered)'
24
+ task export_translations: :environment do
28
25
  source_dir = I18nDocs::CsvToYaml.root_path.join('config', 'locales')
29
26
  output_dir = I18nDocs::CsvToYaml.root_path.join('tmp')
30
27
  locales = I18n.available_locales
31
28
 
32
29
  input_files = Dir[File.join(source_dir, ENV['locale'] || 'en', '*.yml')]
33
30
 
34
- puts ""
31
+ puts ''
35
32
  puts " Detected locales: #{locales}"
36
- puts " Detected files:"
37
- input_files.each {|f| puts " * #{File.basename(f)}" }
33
+ puts ' Detected files:'
34
+ input_files.each { |f| puts " * #{File.basename(f)}" }
38
35
 
39
- puts ""
40
- puts " Start exporting files:"
36
+ puts ''
37
+ puts ' Start exporting files:'
41
38
 
42
39
  input_files.each do |file|
43
40
  file = File.basename(file)
@@ -45,9 +42,8 @@ namespace :i18n do
45
42
  exporter.export
46
43
  end
47
44
 
48
- puts ""
49
- puts " CSV files can be removed safely after uploading them manually to Google Spreadsheet."
50
- puts ""
45
+ puts ''
46
+ puts ' CSV files can be removed safely after uploading them manually to Google Spreadsheet.'
47
+ puts ''
51
48
  end
52
-
53
49
  end
data/test/test_helper.rb CHANGED
@@ -1,12 +1,15 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
1
4
  require 'test/unit'
2
5
  require 'fileutils'
3
6
  require 'mocha/setup'
7
+
4
8
  require 'i18n-docs'
5
9
 
6
10
  Rails = Struct.new(:dummy)
7
11
 
8
12
  module TestHelper
9
-
10
13
  def fixture_path
11
14
  File.join(File.expand_path(File.dirname(__FILE__)), 'fixtures')
12
15
  end
@@ -16,11 +19,10 @@ module TestHelper
16
19
  end
17
20
 
18
21
  def create_tmp_dir
19
- FileUtils::mkdir(tmp_dir) if ! File.exist?(tmp_dir)
22
+ FileUtils.mkdir(tmp_dir) unless File.exist?(tmp_dir)
20
23
  end
21
24
 
22
25
  def remove_tmp_dir
23
- FileUtils::rmtree(tmp_dir)
26
+ FileUtils.rmtree(tmp_dir)
24
27
  end
25
-
26
28
  end
@@ -3,7 +3,6 @@ require 'test_helper'
3
3
  # run test: ruby -I test/ -I lib/ test/unit/csv_to_yaml_test.rb
4
4
 
5
5
  module UnitTests
6
-
7
6
  class CsvToYamlTest < Test::Unit::TestCase
8
7
  include TestHelper
9
8
 
@@ -12,9 +11,9 @@ module UnitTests
12
11
 
13
12
  @input_file = File.join(fixture_path, 'minimal.csv')
14
13
  @output_file = File.join(tmp_dir, 'test.yml')
15
- @locales = ['de', 'en']
14
+ @locales = %w[de en]
16
15
 
17
- Rails.stubs(:root).returns(stub(:join => @output_file))
16
+ Rails.stubs(:root).returns(stub(join: @output_file))
18
17
 
19
18
  @csv_to_yaml = I18nDocs::CsvToYaml.new(@input_file, @output_file, @locales)
20
19
  end
@@ -24,8 +23,8 @@ module UnitTests
24
23
  end
25
24
 
26
25
  def test_process_row
27
- row1 = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => 'Telefonbuch der Schweiz'}
28
- row2 = {'key' => 'homepage.welcome', 'en' => 'Welcome', 'de' => 'Willkommen'}
26
+ row1 = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => 'Telefonbuch der Schweiz' }
27
+ row2 = { 'key' => 'homepage.welcome', 'en' => 'Welcome', 'de' => 'Willkommen' }
29
28
  @csv_to_yaml.process_row(row1)
30
29
  @csv_to_yaml.process_row(row2)
31
30
 
@@ -37,8 +36,8 @@ module UnitTests
37
36
  end
38
37
 
39
38
  def test_empty_row
40
- row1 = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => 'Telefonbuch der Schweiz'}
41
- row2 = {'key' => nil, 'en' => 'Welcome', 'de' => 'Willkommen'}
39
+ row1 = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => 'Telefonbuch der Schweiz' }
40
+ row2 = { 'key' => nil, 'en' => 'Welcome', 'de' => 'Willkommen' }
42
41
  @csv_to_yaml.process_row(row1)
43
42
  @csv_to_yaml.process_row(row2)
44
43
 
@@ -48,18 +47,18 @@ module UnitTests
48
47
  end
49
48
 
50
49
  def test_row_containing_non_locale_columns
51
- row = {'key' => 'homepage.title', 'en' => "We are the Phonebook", 'de' => 'Test DE', 'comment' => "Test comment"}
50
+ row = { 'key' => 'homepage.title', 'en' => 'We are the Phonebook', 'de' => 'Test DE',
51
+ 'comment' => 'Test comment' }
52
52
  @csv_to_yaml.process_row(row)
53
53
 
54
54
  translations = @csv_to_yaml.translations
55
55
  assert_equal 'We are the Phonebook', translations['en']['homepage']['title']
56
56
  end
57
57
 
58
-
59
58
  def test_empty_string_replacement_value
60
59
  # As Google Spreadsheet does not export empty cells we use '_' as a fake whitespace which
61
60
  # we replace with an empty string during CVS2YAML conversion.
62
- row = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => '_'}
61
+ row = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => '_' }
63
62
  @csv_to_yaml.process_row(row)
64
63
 
65
64
  translations = @csv_to_yaml.translations
@@ -67,9 +66,8 @@ module UnitTests
67
66
  assert_equal 'Phonebook of Switzerland', translations['en']['homepage']['meta']['title']
68
67
  end
69
68
 
70
-
71
69
  def test_empty_string_value
72
- row = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => ''}
70
+ row = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => '' }
73
71
  @csv_to_yaml.process_row(row)
74
72
 
75
73
  translations = @csv_to_yaml.translations
@@ -77,9 +75,8 @@ module UnitTests
77
75
  assert_equal 'Phonebook of Switzerland', translations['en']['homepage']['meta']['title']
78
76
  end
79
77
 
80
-
81
78
  def test_space_value
82
- row = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => ' '}
79
+ row = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => ' ' }
83
80
  @csv_to_yaml.process_row(row)
84
81
 
85
82
  translations = @csv_to_yaml.translations
@@ -88,7 +85,7 @@ module UnitTests
88
85
  end
89
86
 
90
87
  def test_nil_value
91
- row = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => nil}
88
+ row = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => nil }
92
89
  @csv_to_yaml.process_row(row)
93
90
 
94
91
  translations = @csv_to_yaml.translations
@@ -96,10 +93,9 @@ module UnitTests
96
93
  assert_equal 'Phonebook of Switzerland', translations['en']['homepage']['meta']['title']
97
94
  end
98
95
 
99
-
100
96
  def test_nil_value_deep_structure
101
- row1 = {'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => nil}
102
- row2 = {'key' => 'homepage.welcome', 'en' => 'Welcome', 'de' => 'Willkommen'}
97
+ row1 = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland', 'de' => nil }
98
+ row2 = { 'key' => 'homepage.welcome', 'en' => 'Welcome', 'de' => 'Willkommen' }
103
99
  @csv_to_yaml.process_row(row1)
104
100
  @csv_to_yaml.process_row(row2)
105
101
 
@@ -109,15 +105,28 @@ module UnitTests
109
105
  assert_equal 'Phonebook of Switzerland', translations['en']['homepage']['meta']['title']
110
106
  end
111
107
 
108
+ def test_row_for_missing_locale_key
109
+ row = { 'key' => 'homepage.meta.title', 'en' => 'Phonebook of Switzerland' }
110
+ assert_raise RuntimeError.new('Locale missing for key homepage.meta.title! (locales in app: ["de", "en"] / locales in file: ["en"])') do
111
+ @csv_to_yaml.process_row(row)
112
+ end
113
+ end
112
114
 
113
115
  def test_store_translations
114
- keys = ['homepage', 'meta', 'title']
116
+ keys = %w[homepage meta title]
115
117
  @csv_to_yaml.store_translation(keys, 'de', 'Telefonbuch der Schweiz')
116
118
 
117
119
  translations = @csv_to_yaml.translations
118
120
  assert_equal 'Telefonbuch der Schweiz', translations['de']['homepage']['meta']['title']
119
121
  end
120
122
 
123
+ def test_store_translations_with_faulty_locale
124
+ keys = %w[homepage meta title]
125
+ assert_raise RuntimeError.new("Error around key 'homepage.meta.title': Expected nil to be a Hash") do
126
+ @csv_to_yaml.store_translation(keys, 'zz', 'Telefonbuch der Schweiz')
127
+ end
128
+ end
129
+
121
130
  def test_process
122
131
  @locales.each do |locale|
123
132
  assert_empty @csv_to_yaml.translations[locale], "expected translation hash for locale '#{locale}' to be empty"
@@ -141,7 +150,7 @@ module UnitTests
141
150
  end
142
151
 
143
152
  def test_key_has_spaces
144
- row = {'key' => 'has. space', 'en' => 'yes', 'de' => 'ja'}
153
+ row = { 'key' => 'has. space', 'en' => 'yes', 'de' => 'ja' }
145
154
  @csv_to_yaml.process_row(row)
146
155
 
147
156
  translations = @csv_to_yaml.translations
@@ -153,10 +162,9 @@ module UnitTests
153
162
  @input_file = File.join(fixture_path, 'error.csv')
154
163
  @csv_to_yaml = I18nDocs::CsvToYaml.new(@input_file, @output_file, @locales)
155
164
 
156
- assert_raise "Error around key 'top_level.key.another_key': Expected \"Value2\" to be a Hash" do
165
+ assert_raise RuntimeError.new("Error around key 'top_level.key.another_key': Expected \"Value2\" to be a Hash") do
157
166
  @csv_to_yaml.process
158
167
  end
159
168
  end
160
-
161
169
  end
162
170
  end
@@ -12,7 +12,7 @@ module UnitTests
12
12
  source_dir = fixture_path
13
13
  source_file = 'header.yml'
14
14
  output_dir = tmp_dir
15
- locales = ['en', 'de']
15
+ locales = %w[en de]
16
16
 
17
17
  @exporter = I18nDocs::TranslationFileExport.new(source_dir, source_file, output_dir, locales)
18
18
  @output_file = File.join(output_dir, 'header.csv')
@@ -22,30 +22,28 @@ module UnitTests
22
22
  remove_tmp_dir
23
23
  end
24
24
 
25
-
26
25
  def test_export
27
26
  assert !File.exist?(@output_file)
28
27
  @exporter.export
29
- assert File.exist?(@output_file), "Expected to have a CSV file written"
28
+ assert File.exist?(@output_file), 'Expected to have a CSV file written'
30
29
  end
31
30
 
32
31
  def dtest_load_language
33
32
  translations = @exporter.load_language('de')
34
33
 
35
- assert translations, "Expected to return a hash with translations"
36
- assert_equal translations['header']['search'], "Finden"
34
+ assert translations, 'Expected to return a hash with translations'
35
+ assert_equal translations['header']['search'], 'Finden'
37
36
  end
38
37
 
39
38
  def dtest_flatten_translations_hash
40
- translation_hash = {'a' => {
41
- 'I' => '1',
42
- 'II' => '2',
43
- 'III' => {
44
- 'Z' => '3'
45
- }
46
- },
47
- 'b' => '4'
48
- }
39
+ translation_hash = { 'a' => {
40
+ 'I' => '1',
41
+ 'II' => '2',
42
+ 'III' => {
43
+ 'Z' => '3'
44
+ }
45
+ },
46
+ 'b' => '4' }
49
47
 
50
48
  flat = @exporter.flatten_translations_hash(translation_hash, [])
51
49
  assert_equal '1', flat['a.I']
@@ -66,8 +64,8 @@ module UnitTests
66
64
  end
67
65
 
68
66
  def dtest_write_to_csv
69
- @exporter.translations = {'de' => {'numbers.one' => 'eins'},
70
- 'en' => {'numbers.one' => 'one'}}
67
+ @exporter.translations = { 'de' => { 'numbers.one' => 'eins' },
68
+ 'en' => { 'numbers.one' => 'one' } }
71
69
 
72
70
  @exporter.write_to_csv
73
71
 
@@ -75,7 +73,5 @@ module UnitTests
75
73
  assert_match(/^key,(en|de|,){3}$/, output)
76
74
  assert_match(/^numbers.one,(one|eins|,){3}$/, output)
77
75
  end
78
-
79
-
80
76
  end
81
77
  end
@@ -12,13 +12,13 @@ module UnitTests
12
12
  config_file = File.join(fixture_path, 'config.yml')
13
13
  @translations = I18nDocs::Translations.new(config_file, tmp_dir)
14
14
  @translations.tmp_folder = tmp_dir
15
- @translations.locales = ['de', 'en']
15
+ @translations.locales = %w[de en]
16
16
 
17
17
  @fixture_file = File.join(fixture_path, 'minimal.csv')
18
18
  @tmp_file = File.join(tmp_dir, 'downloaded.csv')
19
19
  @output_file = File.join(tmp_dir, 'test.yml')
20
20
 
21
- Rails.stubs(:root).returns(stub(:join => @output_file))
21
+ Rails.stubs(:root).returns(stub(join: @output_file))
22
22
  end
23
23
 
24
24
  def teardown
@@ -27,22 +27,23 @@ module UnitTests
27
27
 
28
28
  def test_download
29
29
  assert !File.exist?(@tmp_file)
30
- @translations.download("https://docs.google.com/spreadsheets/d/1PbmkqamXuNyP7gnVARpeCfV8rA7WvX98dTqsQB3Wdts/pub?output=csv", @tmp_file)
30
+ sheet_url = 'https://docs.google.com/spreadsheets/d/1PbmkqamXuNyP7gnVARpeCfV8rA7WvX98dTqsQB3Wdts/pub?output=csv'
31
+ @translations.download(sheet_url, @tmp_file)
31
32
  assert File.exist?(@tmp_file), "Expected to have downloaded Google Spreadsheet to '#{@tmp_file}'"
32
33
  end
33
34
 
34
35
  def test_cleanup
35
- @translations.csv_files = {'dummy.yml' => @tmp_file}
36
- File.open(@tmp_file, "w") {}
36
+ @translations.csv_files = { 'dummy.yml' => @tmp_file }
37
+ File.open(@tmp_file, 'w') {}
37
38
  assert File.exist?(@tmp_file)
38
39
  @translations.clean_up
39
- assert !File.exist?(@tmp_file), "Expected to delete file"
40
+ assert !File.exist?(@tmp_file), 'Expected to delete file'
40
41
  end
41
42
 
42
43
  def test_store_translations
43
44
  assert !File.exist?(@output_file)
44
45
 
45
- @translations.csv_files = {@output_file => @fixture_file}
46
+ @translations.csv_files = { @output_file => @fixture_file }
46
47
  @translations.store_translations
47
48
 
48
49
  assert File.exist?(@output_file)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georg Kunz
@@ -58,6 +58,34 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: 3.1.7
61
+ - !ruby/object:Gem::Dependency
62
+ name: simplecov
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.16.1
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.16.1
75
+ - !ruby/object:Gem::Dependency
76
+ name: rubocop
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.48.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.48.0
61
89
  description: 'GEM providing helper scripts to manage i18n translations in Google Docs.
62
90
  Features: check YAML files for missing translations; export YAML files to CSV; download
63
91
  translations from multiple Google spreadsheets and store to YAML files'
@@ -66,7 +94,11 @@ executables: []
66
94
  extensions: []
67
95
  extra_rdoc_files: []
68
96
  files:
97
+ - ".codeclimate.yml"
98
+ - ".github/workflows/ci.yml"
69
99
  - ".gitignore"
100
+ - ".rubocop.yml"
101
+ - ".rubocop_todo.yml"
70
102
  - Gemfile
71
103
  - LICENSE.md
72
104
  - README.md
@@ -107,8 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
139
  - !ruby/object:Gem::Version
108
140
  version: '0'
109
141
  requirements: []
110
- rubyforge_project:
111
- rubygems_version: 2.6.5
142
+ rubygems_version: 3.1.6
112
143
  signing_key:
113
144
  specification_version: 4
114
145
  summary: Maintain translations in Google Docs and export them to your Rails project.