i18n-docs 0.0.4 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
+ # i18n-docs
1
2
 
2
- # ![local.ch](http://www.local.ch/favicon.ico) local.ch i18n helpers
3
+ **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.
3
4
 
4
- **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.
5
+ Although we use it with Google Docs, it could be used with any CSV file.
5
6
 
6
- Although we at use it with Google Docs, it could be used with any CSV file.
7
+ *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.*
7
8
 
8
- ## Features:
9
+ ## Features:
9
10
 
10
11
  * download translations from multiple Google spreadsheets and store to YAML files
11
12
  * import/export YAML files with a Google Spreadsheet
@@ -13,27 +14,35 @@ Although we at use it with Google Docs, it could be used with any CSV file.
13
14
 
14
15
  ## Usage
15
16
 
17
+ ### Configuration
18
+
16
19
  Add the GEM to your Rails project:
17
20
 
18
21
  gem 'i18n-docs'
19
22
 
20
- The rake task `i18n:import_translations` requires following configuration file in `config/translations.yml`:
23
+ Create a configuration file in `config/translations.yml`:
21
24
 
22
25
  files:
23
- naviagion.yml: "https://docs.google.com/spreadsheet/pub?key=ab43...34f3&single=true&gid=0&output=csv"
26
+ navigation.yml: "https://docs.google.com/spreadsheet/pub?key=ab43...34f3&single=true&gid=0&output=csv"
24
27
  forms.yml: "https://docs.google.com/spreadsheet/pub?key=0Ap...XveWc&single=true&gid=0&output=csv"
28
+ ... etc ...
29
+
30
+ Finally, let Rails know what locales you will be using. Add this to `config/application.rb`:
31
+
32
+ # locals to support:
33
+ I18n.available_locales = [:en,:de,:it,:fr]
25
34
 
26
- This defines which translations files should be created by exporting 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.
35
+ 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.
27
36
 
28
37
  ### Rake Tasks
29
38
 
30
39
  Following Rake tasks are added by the GEM to your Rails project:
31
40
 
32
- * rake i18n:export_translations
33
- Export all language files to CSV files (only files contained in 'en' folder are considered)
34
- * rake i18n:import_translations
41
+ * `rake i18n:export_translations`
42
+ Export all language files to CSV files (ENV 'locale' have to set for non-'en' locales else only files contained in 'en' folder are considered)
43
+ * `rake i18n:import_translations`
35
44
  Download translations from Google Spreadsheet and save them to YAML files.
36
- * rake i18n:missing_keys
45
+ * `rake i18n:missing_keys`
37
46
  Find and list translation keys that do not exist in all locales
38
47
 
39
48
 
@@ -41,12 +50,20 @@ Following Rake tasks are added by the GEM to your Rails project:
41
50
 
42
51
  * At Google Docs, create a new spreadsheet for your translations. The first column is the translation key, the other columns are the languages:
43
52
  ![screenshot](http://dl.dropbox.com/u/385855/Screenshots/bamr.png)
44
- * use option `File -> Publish To the Web`
53
+ * use option `File -> Publish To the Web`
45
54
  ![screenshot](http://dl.dropbox.com/u/385855/Screenshots/2-lp.png)
46
55
  * use **get a link** to generate a unique url that points to the CSV spreadsheet
47
56
  ![screenshot](http://dl.dropbox.com/u/385855/Screenshots/oom_.png)
48
- * 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
57
+ * 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
58
+
59
+ ## Todo
60
+
61
+ *Pull requests welcome!*
49
62
 
63
+ * create mocked tests that do not have to download our sample CSV files
64
+ * automate the creation of files in config/locales
65
+ * automate the detection of which languages are supported
66
+ * validate use with rails 2.x, other 3.x versions
50
67
 
51
68
  ## CHANGELOG
52
69
 
data/i18n-docs.gemspec CHANGED
@@ -1,19 +1,18 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'i18n-docs'
3
- s.version = '0.0.4'
4
- s.date = '2012-04-20'
3
+ s.version = '0.0.7'
4
+ s.date = '2013-05-10'
5
5
  s.summary = "Maintain translations in Google Docs and export them to your Rails project."
6
6
  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"
7
- s.authors = ["Georg Kunz", "Ivan Jovanovic", "Jeremy Seitz"]
7
+ s.authors = ["Georg Kunz", "Ivan Jovanovic", "Jeremy Seitz", "Eduard Schäli", "Robin Wu", "Esteban Pastorino"]
8
8
  s.email = 'jeremy.seitz@local.ch'
9
9
  s.files = `git ls-files`.split("\n")
10
10
  s.homepage = 'https://github.com/local-ch/i18n-docs'
11
11
 
12
12
  # dependencies
13
- s.add_dependency('bundler')
14
13
  s.add_dependency('rake')
15
-
16
- s.add_development_dependency('mocha')
14
+
15
+ s.add_development_dependency('mocha', '~> 0.13.3')
17
16
  s.add_development_dependency('awesome_print')
18
-
17
+
19
18
  end
@@ -19,7 +19,12 @@ module LocalchI18n
19
19
 
20
20
  def write_files
21
21
  @locales.each do |locale|
22
- output_file_path = defined?(Rails) ? Rails.root.join('config', 'locales', locale, @output_file) : "#{locale}_#{@output_file}"
22
+ if defined?(Rails)
23
+ output_file_path = Rails.root.join('config', 'locales', locale, @output_file)
24
+ FileUtils.mkdir_p File.dirname(output_file_path)
25
+ else
26
+ output_file_path = "#{locale}_#{@output_file}"
27
+ end
23
28
  File.open(output_file_path, 'w') do |file|
24
29
  final_translation_hash = {locale => @translations[locale]}
25
30
  file.puts YAML::dump(final_translation_hash)
@@ -1,4 +1,4 @@
1
- #
1
+ # encoding: utf-8
2
2
  # Order of method calls
3
3
  # download_files
4
4
  # store_translations
@@ -6,32 +6,34 @@
6
6
  #
7
7
  module LocalchI18n
8
8
  class Translations
9
-
9
+
10
10
  attr_accessor :locales, :tmp_folder, :config_file, :csv_files
11
-
11
+
12
12
  def initialize(config_file = nil, tmp_folder = nil)
13
- @config_file = config_file
13
+ @config_file = config_file
14
14
  @tmp_folder = tmp_folder
15
-
15
+
16
16
  @csv_files = {}
17
-
17
+
18
18
  load_config
19
19
  load_locales
20
20
  end
21
-
21
+
22
22
  def load_locales
23
23
  @locales = []
24
24
  @locales = I18n.available_locales if defined?(I18n)
25
25
  end
26
-
26
+
27
27
  def load_config
28
28
  @settings = {}
29
29
  @settings = YAML.load_file(config_file) if File.exists?(config_file)
30
30
  end
31
-
31
+
32
32
  def download_files
33
33
  files = @settings['files']
34
34
  files.each do |target_file, url|
35
+ #ensure .yml filename
36
+ target_file = target_file + ".yml" if target_file !~ /\.yml$/
35
37
  # download file to tmp directory
36
38
  tmp_file = File.basename(target_file).gsub('.yml', '.csv')
37
39
  tmp_file = File.join(@tmp_folder, tmp_file)
@@ -39,31 +41,32 @@ module LocalchI18n
39
41
  @csv_files[target_file] = tmp_file
40
42
  end
41
43
  end
42
-
44
+
43
45
  def store_translations
44
46
  @csv_files.each do |target_file, csv_file|
45
47
  converter = CsvToYaml.new(csv_file, target_file, @locales)
46
48
  converter.process
47
49
  converter.write_files
48
50
  end
49
-
51
+
50
52
  @csv_files
51
53
  end
52
-
54
+
53
55
  def clean_up
54
56
  # remove all tmp files
55
57
  @csv_files.each do |target_file, csv_file|
56
58
  File.unlink(csv_file)
57
59
  end
58
60
  end
59
-
61
+
60
62
  def download(url, destination_file)
61
63
  puts "Download '#{url}' to '#{destination_file}'"
64
+ doc_data = open(url).read.force_encoding('UTF-8')
62
65
  File.open(destination_file, 'w') do |dst|
63
- dst.write(open(url).read)
66
+ dst.write(doc_data)
64
67
  end
65
68
  end
66
-
69
+
67
70
  end
68
71
  end
69
72
 
@@ -1,57 +1,57 @@
1
1
 
2
2
  namespace :i18n do
3
-
3
+
4
4
  desc "Find and list translation keys that do not exist in all locales"
5
5
  task :missing_keys => :environment do
6
6
  finder = LocalchI18n::MissingKeysFinder.new(I18n.backend)
7
7
  finder.find_missing_keys
8
8
  end
9
-
9
+
10
10
  desc "Download translations from Google Spreadsheet and save them to YAML files."
11
11
  task :import_translations => :environment do
12
12
  raise "'Rails' not found! Tasks can only run within a Rails application!" if !defined?(Rails)
13
-
13
+
14
14
  config_file = Rails.root.join('config', 'translations.yml')
15
15
  raise "No config file 'config/translations.yml' found." if !File.exists?(config_file)
16
-
16
+
17
17
  tmp_dir = Rails.root.join('tmp')
18
-
18
+
19
19
  translations = LocalchI18n::Translations.new(config_file, tmp_dir)
20
20
  translations.download_files
21
21
  translations.store_translations
22
22
  translations.clean_up
23
-
23
+
24
24
  end
25
-
25
+
26
26
  desc "Export all language files to CSV files (only files contained in en folder are considered)"
27
27
  task :export_translations => :environment do
28
28
  raise "'Rails' not found! Tasks can only run within a Rails application!" if !defined?(Rails)
29
-
29
+
30
30
  source_dir = Rails.root.join('config', 'locales')
31
31
  output_dir = Rails.root.join('tmp')
32
32
  locales = I18n.available_locales
33
-
34
- input_files = Dir[File.join(source_dir, 'en', '*.yml')]
35
-
33
+
34
+ input_files = Dir[File.join(source_dir, ENV['locale'] || 'en', '*.yml')]
35
+
36
36
  puts ""
37
37
  puts " Detected locales: #{locales}"
38
38
  puts " Detected files:"
39
39
  input_files.each {|f| puts " * #{File.basename(f)}" }
40
-
40
+
41
41
  puts ""
42
42
  puts " Start exporting files:"
43
-
43
+
44
44
  input_files.each do |file|
45
45
  file = File.basename(file)
46
46
  exporter = LocalchI18n::TranslationFileExport.new(source_dir, file, output_dir, locales)
47
47
  exporter.export
48
48
  end
49
-
49
+
50
50
  puts ""
51
51
  puts " CSV files can be removed safely after uploading them manually to Google Spreadsheet."
52
52
  puts ""
53
53
  end
54
-
54
+
55
55
  end
56
56
 
57
57
 
data/test/test_helper.rb CHANGED
@@ -1,26 +1,29 @@
1
1
  require 'test/unit'
2
2
  require 'fileutils'
3
- require 'localch-i18n'
3
+ require 'mocha/setup'
4
4
 
5
+ require 'i18n-docs'
6
+
7
+ Rails = Struct.new(:dummy)
5
8
 
6
9
  module TestHelper
7
-
10
+
8
11
  def fixture_path
9
12
  File.join(File.expand_path(File.dirname(__FILE__)), 'fixtures')
10
13
  end
11
-
14
+
12
15
  def tmp_dir
13
16
  File.join(fixture_path, 'tmp')
14
17
  end
15
-
18
+
16
19
  def create_tmp_dir
17
20
  FileUtils::mkdir(tmp_dir) if ! File.exists?(tmp_dir)
18
21
  end
19
-
22
+
20
23
  def remove_tmp_dir
21
24
  FileUtils::rmtree(tmp_dir)
22
25
  end
23
-
26
+
24
27
  end
25
28
 
26
29
 
@@ -1,11 +1,7 @@
1
1
  require 'test_helper'
2
- require 'mocha'
3
- require 'awesome_print'
4
2
 
5
3
  # run test: ruby -I test/ -I lib/ test/unit/csv_to_yaml_test.rb
6
4
 
7
- Rails = Struct.new(:dummy)
8
-
9
5
  module UnitTests
10
6
 
11
7
  class CsvToYamlTest < Test::Unit::TestCase
@@ -1,84 +1,81 @@
1
1
  require 'test_helper'
2
- require 'mocha'
3
-
4
- require 'awesome_print'
5
2
 
6
3
  # run test: ruby -I test/ -I lib/ test/unit/locale_builder_test.rb
7
4
 
8
5
  module UnitTests
9
6
  class TranslationFileExportTest < Test::Unit::TestCase
10
7
  include TestHelper
11
-
8
+
12
9
  def setup
13
10
  create_tmp_dir
14
-
11
+
15
12
  source_dir = fixture_path
16
13
  source_file = 'header.yml'
17
14
  output_dir = tmp_dir
18
15
  locales = ['en', 'de']
19
-
16
+
20
17
  @exporter = LocalchI18n::TranslationFileExport.new(source_dir, source_file, output_dir, locales)
21
18
  @output_file = File.join(output_dir, 'header.csv')
22
19
  end
23
-
20
+
24
21
  def teardown
25
22
  remove_tmp_dir
26
23
  end
27
-
28
-
24
+
25
+
29
26
  def test_export
30
27
  assert !File.exists?(@output_file)
31
28
  @exporter.export
32
29
  assert File.exists?(@output_file), "Expected to have a CSV file written"
33
30
  end
34
-
31
+
35
32
  def dtest_load_language
36
33
  translations = @exporter.load_language('de')
37
-
34
+
38
35
  assert translations, "Expected to return a hash with translations"
39
36
  assert_equal translations['header']['search'], "Finden"
40
37
  end
41
-
38
+
42
39
  def dtest_flatten_translations_hash
43
40
  translation_hash = {'a' => {
44
- 'I' => '1',
45
- 'II' => '2',
41
+ 'I' => '1',
42
+ 'II' => '2',
46
43
  'III' => {
47
44
  'Z' => '3'
48
45
  }
49
- },
46
+ },
50
47
  'b' => '4'
51
48
  }
52
-
49
+
53
50
  flat = @exporter.flatten_translations_hash(translation_hash, [])
54
51
  assert_equal '1', flat['a.I']
55
52
  assert_equal '2', flat['a.II']
56
53
  assert_equal '3', flat['a.III.Z']
57
54
  assert_equal '4', flat['b']
58
55
  end
59
-
56
+
60
57
  def dtest_load_translations
61
58
  assert_empty @exporter.translations
62
59
  @exporter.load_translations
63
-
60
+
64
61
  assert @exporter.translations['de']
65
62
  assert @exporter.translations['en']
66
63
  assert_equal 'Finden', @exporter.translations['de']['header.search']
67
64
  assert_equal 'Telefonbuch', @exporter.translations['de']['header.phonebook']
68
65
  assert_equal '(c) local.ch', @exporter.translations['de']['copyright']
69
66
  end
70
-
67
+
71
68
  def dtest_write_to_csv
72
69
  @exporter.translations = {'de' => {'numbers.one' => 'eins'},
73
70
  'en' => {'numbers.one' => 'one'}}
74
-
71
+
75
72
  @exporter.write_to_csv
76
-
73
+
77
74
  output = File.read(@output_file)
78
- assert_match /^key,(en|de|,){3}$/, output
79
- assert_match /^numbers.one,(one|eins|,){3}$/, output
75
+ assert_match(/^key,(en|de|,){3}$/, output)
76
+ assert_match(/^numbers.one,(one|eins|,){3}$/, output)
80
77
  end
81
-
82
-
78
+
79
+
83
80
  end
84
- end
81
+ end
@@ -1,39 +1,36 @@
1
1
  require 'test_helper'
2
- require 'mocha'
3
2
 
4
3
  # run test: ruby -I test/ -I lib/ test/unit/locale_builder_test.rb
5
4
 
6
- Rails = Struct.new(:dummy)
7
-
8
5
  module UnitTests
9
6
  class TranslationsTest < Test::Unit::TestCase
10
7
  include TestHelper
11
-
8
+
12
9
  def setup
13
10
  create_tmp_dir
14
-
11
+
15
12
  config_file = File.join(fixture_path, 'config.yml')
16
13
  @translations = LocalchI18n::Translations.new(config_file, tmp_dir)
17
14
  @translations.tmp_folder = tmp_dir
18
15
  @translations.locales = ['de', 'en']
19
-
16
+
20
17
  @fixture_file = File.join(fixture_path, 'minimal.csv')
21
18
  @tmp_file = File.join(tmp_dir, 'downloaded.csv')
22
19
  @output_file = File.join(tmp_dir, 'test.yml')
23
-
20
+
24
21
  Rails.stubs(:root).returns(stub(:join => @output_file))
25
22
  end
26
-
23
+
27
24
  def teardown
28
25
  remove_tmp_dir
29
26
  end
30
-
27
+
31
28
  def test_download
32
29
  assert !File.exists?(@tmp_file)
33
30
  @translations.download("https://docs.google.com/spreadsheet/pub?key=0ApnemdIdiDXedEpiVFR1RkdWMDhnTTgtdzRJMWZMLUE&single=true&gid=0&output=csv", @tmp_file)
34
31
  assert File.exists?(@tmp_file), "Expected to have downloaded Google Spreadsheet to '#{@tmp_file}'"
35
32
  end
36
-
33
+
37
34
  def test_cleanup
38
35
  @translations.csv_files = {'dummy.yml' => @tmp_file}
39
36
  File.open(@tmp_file, "w") {}
@@ -41,22 +38,23 @@ module UnitTests
41
38
  @translations.clean_up
42
39
  assert !File.exists?(@tmp_file), "Expected to delete file"
43
40
  end
44
-
41
+
45
42
  def test_store_translations
46
43
  assert !File.exists?(@output_file)
47
-
44
+
48
45
  @translations.csv_files = {@output_file => @fixture_file}
49
46
  @translations.store_translations
50
-
47
+
51
48
  assert File.exists?(@output_file)
52
49
  end
53
-
50
+
54
51
  def test_download_files
55
52
  expected_file = File.join(tmp_dir, 'download.csv')
56
53
  assert !File.exists?(expected_file)
57
54
  @translations.download_files
58
55
  assert File.exists?(expected_file)
56
+ assert File.open(expected_file).read.encoding.name == 'UTF-8'
59
57
  end
60
-
58
+
61
59
  end
62
- end
60
+ end
metadata CHANGED
@@ -1,34 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Georg Kunz
9
9
  - Ivan Jovanovic
10
10
  - Jeremy Seitz
11
+ - Eduard Schäli
12
+ - Robin Wu
13
+ - Esteban Pastorino
11
14
  autorequire:
12
15
  bindir: bin
13
16
  cert_chain: []
14
- date: 2012-04-20 00:00:00.000000000 Z
17
+ date: 2013-05-10 00:00:00.000000000 Z
15
18
  dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: bundler
18
- requirement: !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ! '>='
22
- - !ruby/object:Gem::Version
23
- version: '0'
24
- type: :runtime
25
- prerelease: false
26
- version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
- requirements:
29
- - - ! '>='
30
- - !ruby/object:Gem::Version
31
- version: '0'
32
19
  - !ruby/object:Gem::Dependency
33
20
  name: rake
34
21
  requirement: !ruby/object:Gem::Requirement
@@ -50,17 +37,17 @@ dependencies:
50
37
  requirement: !ruby/object:Gem::Requirement
51
38
  none: false
52
39
  requirements:
53
- - - ! '>='
40
+ - - ~>
54
41
  - !ruby/object:Gem::Version
55
- version: '0'
42
+ version: 0.13.3
56
43
  type: :development
57
44
  prerelease: false
58
45
  version_requirements: !ruby/object:Gem::Requirement
59
46
  none: false
60
47
  requirements:
61
- - - ! '>='
48
+ - - ~>
62
49
  - !ruby/object:Gem::Version
63
- version: '0'
50
+ version: 0.13.3
64
51
  - !ruby/object:Gem::Dependency
65
52
  name: awesome_print
66
53
  requirement: !ruby/object:Gem::Requirement
@@ -119,22 +106,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
106
  - - ! '>='
120
107
  - !ruby/object:Gem::Version
121
108
  version: '0'
122
- segments:
123
- - 0
124
- hash: -754739510145724626
125
109
  required_rubygems_version: !ruby/object:Gem::Requirement
126
110
  none: false
127
111
  requirements:
128
112
  - - ! '>='
129
113
  - !ruby/object:Gem::Version
130
114
  version: '0'
131
- segments:
132
- - 0
133
- hash: -754739510145724626
134
115
  requirements: []
135
116
  rubyforge_project:
136
- rubygems_version: 1.8.19
117
+ rubygems_version: 1.8.24
137
118
  signing_key:
138
119
  specification_version: 3
139
120
  summary: Maintain translations in Google Docs and export them to your Rails project.
140
121
  test_files: []
122
+ has_rdoc: