i18n-one_sky 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +2 -0
- data/Gemfile.lock +19 -17
- data/README.rdoc +8 -8
- data/Rakefile +11 -1
- data/i18n-one_sky.gemspec +5 -5
- data/lib/generators/one_sky/init/init_generator.rb +28 -11
- data/lib/generators/one_sky/init_active_record_backend/init_active_record_backend_generator.rb +6 -3
- data/lib/generators/one_sky/init_active_record_backend/templates/active_record_backend.rb +13 -0
- data/lib/generators/one_sky/init_active_record_backend/templates/migration.rb +1 -0
- data/lib/i18n-one_sky.rb +1 -19
- data/lib/i18n/one_sky.rb +15 -0
- data/lib/i18n/one_sky/active_record_client.rb +53 -0
- data/lib/i18n/one_sky/client_base.rb +153 -0
- data/lib/{i18n-one_sky → i18n/one_sky}/rails/railtie.rb +2 -2
- data/lib/i18n/one_sky/rails/tasks/i18n-one_sky.rake +45 -0
- data/lib/i18n/one_sky/simple_client.rb +65 -0
- data/lib/{i18n-one_sky → i18n/one_sky}/version.rb +1 -1
- data/spec/active_record_client_spec.rb +104 -0
- data/spec/{data → fixtures/files}/en.yml +0 -0
- data/spec/simple_client_spec.rb +68 -44
- data/spec/spec_helper.rb +2 -0
- metadata +34 -28
- data/lib/generators/one_sky/init_active_record_backend/templates/onesky.rb +0 -4
- data/lib/i18n-one_sky/rails/tasks/i18n-one_sky.rake +0 -24
- data/lib/i18n-one_sky/simple_client.rb +0 -162
- data/spec/helpers.rb +0 -22
data/.rspec
ADDED
data/Gemfile.lock
CHANGED
@@ -1,40 +1,42 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
i18n-one_sky (0.0
|
5
|
-
|
6
|
-
i18n
|
7
|
-
|
8
|
-
|
4
|
+
i18n-one_sky (2.0.0)
|
5
|
+
activesupport (>= 2.2.2)
|
6
|
+
i18n (>= 0.5.0)
|
7
|
+
i18n-active_record (>= 0.0.2)
|
8
|
+
one_sky (= 2.0.0)
|
9
9
|
|
10
10
|
GEM
|
11
11
|
remote: http://rubygems.org/
|
12
12
|
specs:
|
13
|
-
|
14
|
-
|
13
|
+
activesupport (3.1.3)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
diff-lcs (1.1.3)
|
16
|
+
i18n (0.6.0)
|
15
17
|
i18n-active_record (0.0.2)
|
16
18
|
i18n (>= 0.5.0)
|
17
|
-
json (1.
|
18
|
-
mime-types (1.
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
json (1.6.3)
|
20
|
+
mime-types (1.17.2)
|
21
|
+
multi_json (1.0.4)
|
22
|
+
one_sky (2.0.0)
|
23
|
+
json (>= 1.4.0)
|
24
|
+
rest-client (>= 1.4.0)
|
22
25
|
rest-client (1.6.7)
|
23
26
|
mime-types (>= 1.16)
|
24
27
|
rspec (2.2.0)
|
25
28
|
rspec-core (~> 2.2)
|
26
29
|
rspec-expectations (~> 2.2)
|
27
30
|
rspec-mocks (~> 2.2)
|
28
|
-
rspec-core (2.
|
29
|
-
rspec-expectations (2.
|
31
|
+
rspec-core (2.7.1)
|
32
|
+
rspec-expectations (2.7.0)
|
30
33
|
diff-lcs (~> 1.1.2)
|
31
|
-
rspec-mocks (2.
|
32
|
-
thor (0.14.6)
|
34
|
+
rspec-mocks (2.7.0)
|
33
35
|
|
34
36
|
PLATFORMS
|
35
37
|
ruby
|
36
38
|
|
37
39
|
DEPENDENCIES
|
38
|
-
bundler (
|
40
|
+
bundler (>= 1.0.0)
|
39
41
|
i18n-one_sky!
|
40
42
|
rspec (~> 2.2.0)
|
data/README.rdoc
CHANGED
@@ -22,17 +22,17 @@ Then tell Bundler to install:
|
|
22
22
|
|
23
23
|
If you haven't done so yet, log in to your account at OneSky[link:http://www.oneskyapp.com] and create a new project for this Rails app. Also, find the API key and secret which you will supply here:
|
24
24
|
|
25
|
-
rails generate one_sky:init my_api_key my_api_secret my_project
|
25
|
+
rails generate one_sky:init my_api_key my_api_secret my_project my_platform_id
|
26
26
|
|
27
27
|
This will create the configuration file config/one_sky.yml.
|
28
28
|
|
29
29
|
So assuming that you already have your phrases defined for your default locale and all your views contain the ubiquitous t() methods, it's time now to submit these phrases to OneSky:
|
30
30
|
|
31
|
-
rake one_sky:
|
31
|
+
rake one_sky:upload
|
32
32
|
|
33
33
|
Then ask your translators to provide the translations using the OneSky[link:http://www.oneskyapp.com] website. When they're done and a few new languages are available, download them by:
|
34
34
|
|
35
|
-
rake one_sky:
|
35
|
+
rake one_sky:download
|
36
36
|
|
37
37
|
This will save the translations inside config/locales/*_one_sky.yml files. You now have more languages supported and it's just a matter of pushing again to production. You can call upload and download over and over as you incrementally internationalize your site.
|
38
38
|
|
@@ -48,21 +48,21 @@ And see I18n::OneSky::SimpleClient for the methods available in Ruby.
|
|
48
48
|
|
49
49
|
= Using Database as translation storage, YAML as fallback (since version 0.0.3, Rails only)
|
50
50
|
|
51
|
-
|
51
|
+
The following command generates rails initializers and run db migration:
|
52
52
|
|
53
53
|
rails generate one_sky:init_active_record_backend
|
54
54
|
|
55
55
|
use the upload_phrases rake command to upload your default locale to one sky server:
|
56
56
|
|
57
|
-
rake one_sky:
|
57
|
+
rake one_sky:active_record:upload
|
58
58
|
|
59
|
-
Then, instead of running one_sky:
|
59
|
+
Then, instead of running one_sky:download, run the following command to download and store the translations into translations database table:
|
60
60
|
|
61
|
-
rake one_sky:
|
61
|
+
rake one_sky:active_record:download
|
62
62
|
|
63
63
|
= Using i18n-one_sky gem in Heroku
|
64
64
|
|
65
|
-
Because Heroku is read-only file system, you have to use database storage as storage backend. Either configure the "ONESKY_API_KEY", "ONESKY_API_SECRET"
|
65
|
+
Because Heroku is read-only file system, you have to use database storage as storage backend. Either configure the "ONESKY_API_KEY", "ONESKY_API_SECRET", "ONESKY_PROJECT", "ONESKY_PLATFORM_ID" environment variables manually or use the OneSky Heroku addon.
|
66
66
|
|
67
67
|
Read "Using Database as translation storage" sections for details to upload and download phrases.
|
68
68
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'bundler'
|
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
4
|
# = RDoc
|
5
|
-
require '
|
5
|
+
require 'rdoc/task'
|
6
6
|
|
7
7
|
Rake::RDocTask.new do |t|
|
8
8
|
t.rdoc_dir = 'rdoc'
|
@@ -11,3 +11,13 @@ Rake::RDocTask.new do |t|
|
|
11
11
|
t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'CHANGELOG', 'CREDITS', 'lib/**/*.rb')
|
12
12
|
end
|
13
13
|
|
14
|
+
require 'rspec/core/rake_task'
|
15
|
+
|
16
|
+
desc 'Default: run specs.'
|
17
|
+
task :default => :spec
|
18
|
+
|
19
|
+
desc "Run specs"
|
20
|
+
RSpec::Core::RakeTask.new do |t|
|
21
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
22
|
+
# Put spec opts in a file named .rspec in root
|
23
|
+
end
|
data/i18n-one_sky.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "i18n
|
3
|
+
require "i18n/one_sky/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "i18n-one_sky"
|
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.rubyforge_project = "i18n-one_sky"
|
16
16
|
|
17
17
|
s.add_dependency "i18n", ">= 0.5.0"
|
18
|
-
s.add_dependency "one_sky", "
|
19
|
-
s.add_dependency 'i18n-active_record', "
|
20
|
-
s.add_dependency "
|
18
|
+
s.add_dependency "one_sky", "2.0.0"
|
19
|
+
s.add_dependency 'i18n-active_record', ">= 0.0.2"
|
20
|
+
s.add_dependency "activesupport", ">= 2.2.2"
|
21
21
|
|
22
22
|
s.add_development_dependency "rspec", "~> 2.2.0"
|
23
|
-
s.add_development_dependency "bundler", "
|
23
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
24
24
|
|
25
25
|
s.files = `git ls-files`.split("\n")
|
26
26
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -2,28 +2,45 @@ module OneSky
|
|
2
2
|
module Generators
|
3
3
|
class InitGenerator < ::Rails::Generators::Base
|
4
4
|
desc "This generator configures i18n-one_sky for use on this Rails project."
|
5
|
-
|
6
|
-
argument :
|
7
|
-
argument :
|
8
|
-
|
9
|
-
|
5
|
+
|
6
|
+
argument :api_key, :type => :string, :desc => "The API key you got from OneSky"
|
7
|
+
argument :api_secret, :type => :string, :desc => "The API secret you got from OneSky"
|
8
|
+
argument :project, :type => :string, :desc => "The name of the OneSky project"
|
9
|
+
argument :platform_id, :type => :string, :desc => "The id of the OneSky platform"
|
10
|
+
|
11
|
+
class_option :force, :type => :boolean, :default => false, :desc => "Overwrite if config file already exists"
|
12
|
+
|
13
|
+
CONFIG_PATH = File.join(Rails.root.to_s, 'config', 'one_sky.yml')
|
10
14
|
|
11
15
|
def remove_config_file
|
12
|
-
if File.exists?
|
16
|
+
if File.exists? CONFIG_PATH
|
13
17
|
if options.force?
|
14
18
|
say_status("warning", "config file already exists and is being overwritten.", :yellow)
|
15
|
-
remove_file
|
19
|
+
remove_file CONFIG_PATH
|
16
20
|
else
|
17
21
|
say_status("error", "config file already exists. Use --force to overwrite.", :red)
|
18
|
-
raise "Error: OneSky config file exists."
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
26
|
+
YAML_COMMENT = <<-YAML
|
27
|
+
#
|
28
|
+
# To load your OneSky details from the environment
|
29
|
+
# just add some erb tags like this.
|
30
|
+
#
|
31
|
+
# api_key: <%= ENV["ONESKY_API_KEY"] %>
|
32
|
+
# api_secret: <%= ENV["ONESKY_API_SECRET"] %>
|
33
|
+
# project: <%= ENV["ONESKY_PROJECT"] %>
|
34
|
+
# platform_id: <%= ENV["ONESKY_PLATFORM_ID"] %>
|
35
|
+
#
|
36
|
+
YAML
|
37
|
+
|
38
|
+
def config_hash
|
39
|
+
{"api_key" => api_key, "api_secret" => api_secret, "project" => project, "platform_id" => platform_id.to_i}
|
40
|
+
end
|
41
|
+
|
23
42
|
def create_config_file
|
24
|
-
|
25
|
-
create_file(@@config_file, config_hash.to_yaml)
|
26
|
-
say_status("info", "config file #{@@config_file} created.", :green)
|
43
|
+
create_file(CONFIG_PATH, YAML_COMMENT+config_hash.to_yaml)
|
27
44
|
end
|
28
45
|
end
|
29
46
|
end
|
data/lib/generators/one_sky/init_active_record_backend/init_active_record_backend_generator.rb
CHANGED
@@ -10,8 +10,11 @@ module OneSky
|
|
10
10
|
source_root File.expand_path("../templates", __FILE__)
|
11
11
|
|
12
12
|
def install_onesky_active_record
|
13
|
-
|
13
|
+
# generate the migration first
|
14
14
|
generate_db_migration
|
15
|
+
|
16
|
+
# then create the initializer (else we cant migrate)
|
17
|
+
generate_initializers
|
15
18
|
end
|
16
19
|
|
17
20
|
def self.next_migration_number(dirname)
|
@@ -25,11 +28,11 @@ module OneSky
|
|
25
28
|
protected
|
26
29
|
|
27
30
|
def generate_initializers
|
28
|
-
copy_file "
|
31
|
+
copy_file "active_record_backend.rb", "config/initializers/active_record_backend.rb"
|
29
32
|
end
|
30
33
|
|
31
34
|
def generate_db_migration
|
32
|
-
migration_template 'migration.rb', 'db/migrate/create_translations_table.rb'
|
35
|
+
migration_template 'migration.rb', 'db/migrate/create_translations_table.rb'
|
33
36
|
rake("db:migrate")
|
34
37
|
end
|
35
38
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'i18n/backend/active_record'
|
2
|
+
|
3
|
+
# flatten and memoize the active record backend
|
4
|
+
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
|
5
|
+
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Flatten)
|
6
|
+
|
7
|
+
# ensure we have migrated before we try and use the backend.
|
8
|
+
if I18n::Backend::ActiveRecord::Translation.table_exists?
|
9
|
+
# chain it into the existing backend
|
10
|
+
I18n.backend = I18n::Backend::Chain.new(I18n.backend, I18n::Backend::ActiveRecord.new)
|
11
|
+
else
|
12
|
+
warn "There is currently no translations table. You may need to migrate."
|
13
|
+
end
|
data/lib/i18n-one_sky.rb
CHANGED
@@ -1,19 +1 @@
|
|
1
|
-
require 'i18n'
|
2
|
-
require 'one_sky'
|
3
|
-
require 'i18n-one_sky/rails/railtie.rb' if defined? Rails
|
4
|
-
require 'i18n/backend/active_record' if defined? ActiveRecord
|
5
|
-
|
6
|
-
module I18n
|
7
|
-
module OneSky
|
8
|
-
autoload :SimpleClient, 'i18n-one_sky/simple_client'
|
9
|
-
class DefaultLocaleMismatchError < StandardError; end
|
10
|
-
|
11
|
-
if defined?(ActiveRecord)
|
12
|
-
module Translator
|
13
|
-
class Backend < I18n::Backend::ActiveRecord
|
14
|
-
include I18n::Backend::Memoize
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
require 'i18n/one_sky'
|
data/lib/i18n/one_sky.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'one_sky'
|
3
|
+
require 'i18n/one_sky/rails/railtie.rb' if defined? Rails
|
4
|
+
|
5
|
+
module I18n
|
6
|
+
module OneSky
|
7
|
+
# we only want to load this when i18n-active_record is in use.
|
8
|
+
autoload :ActiveRecordClient, 'i18n/one_sky/active_record_client'
|
9
|
+
|
10
|
+
class DefaultLocaleMismatchError < StandardError; end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'i18n/one_sky/simple_client'
|
15
|
+
require 'i18n/one_sky/version'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'i18n/backend/active_record'
|
2
|
+
require 'i18n/one_sky/client_base'
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
module OneSky
|
6
|
+
# A class to deal with the OneSky apis
|
7
|
+
# it encapsulates the logic of I18n::Backend::ActiveRecord
|
8
|
+
class ActiveRecordClient < ClientBase
|
9
|
+
|
10
|
+
Translation = I18n::Backend::ActiveRecord::Translation
|
11
|
+
|
12
|
+
def download
|
13
|
+
platform_locales.each do |locale|
|
14
|
+
locale_code = locale["locale"]
|
15
|
+
local_name = locale["name"]["local"]
|
16
|
+
english_name = locale["name"]["eng"]
|
17
|
+
|
18
|
+
i18n_locale_code = locale_os_to_i18n(locale_code)
|
19
|
+
|
20
|
+
if locale_code == platform_base_locale
|
21
|
+
# we skip the base
|
22
|
+
next
|
23
|
+
else
|
24
|
+
yaml = platform.translation.download_yaml(locale_code)
|
25
|
+
YAML.load(yaml).each do |code, translations|
|
26
|
+
puts "Inserting translations:"
|
27
|
+
puts translations.inspect.to_yaml
|
28
|
+
translations.each do |key, value|
|
29
|
+
Translation.locale(i18n_locale_code).delete_all(["key=?", key])
|
30
|
+
Translation.create!(:locale => i18n_locale_code, :key => key.to_s, :value => value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def upload
|
38
|
+
upload_phrases(all_phrases)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Grab all the keys from the active record store.
|
42
|
+
def all_phrases
|
43
|
+
phrases = Hash.new
|
44
|
+
I18n::Backend::ActiveRecord::Translation.locale(I18n.default_locale).find_each() do |translation|
|
45
|
+
phrases[translation.key] = translation.value
|
46
|
+
end
|
47
|
+
phrases
|
48
|
+
end
|
49
|
+
memoize :all_phrases
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'active_support/memoizable'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module OneSky
|
5
|
+
# A base class to deal with the OneSky apis
|
6
|
+
#
|
7
|
+
# Its subclasses;
|
8
|
+
# SimpleClient
|
9
|
+
# ActiveRecordClient
|
10
|
+
#
|
11
|
+
# encapsulate specifics of uploading/downloading for the I18n backends;
|
12
|
+
# I18n::Backend::Simple
|
13
|
+
# I18n::Backend::ActiveRecord
|
14
|
+
class ClientBase
|
15
|
+
extend ActiveSupport::Memoizable
|
16
|
+
|
17
|
+
# The base OneSky project. Gives you low-level access to the API gem.
|
18
|
+
attr_reader :client, :project, :platform
|
19
|
+
|
20
|
+
# Load the client from the one_sky.yml file (installed by `rails generate one_sky:init_generator`)
|
21
|
+
def self.from_config(config_path)
|
22
|
+
if self.config_exists?(config_path)
|
23
|
+
self.new(load_config(config_path))
|
24
|
+
else
|
25
|
+
self.from_env
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Load the client from environment variables.
|
30
|
+
def self.from_env
|
31
|
+
self.new(
|
32
|
+
:api_key => ENV["ONESKY_API_KEY"],
|
33
|
+
:api_secret => ENV["ONESKY_API_SECRET"],
|
34
|
+
:project => ENV["ONESKY_PROJECT"],
|
35
|
+
:platform_id => ENV["ONESKY_PLATFORM_ID"])
|
36
|
+
end
|
37
|
+
|
38
|
+
# Load the one_sky.yml file.
|
39
|
+
# first parsing it as ERB
|
40
|
+
# to enable dynamic config;
|
41
|
+
#
|
42
|
+
# api_key: <%= ENV["ONESKY_API_KEY"] %>
|
43
|
+
# api_secret: <%= ENV["ONESKY_API_SECRET"] %>
|
44
|
+
# project: <%= ENV["ONESKY_PROJECT"] %>
|
45
|
+
# platform_id: <%= ENV["ONESKY_PLATFORM_ID"] %>
|
46
|
+
#
|
47
|
+
def self.load_config(config_path)
|
48
|
+
require 'erb'
|
49
|
+
YAML::load(ERB.new(File.read(config_path)).result).symbolize_keys
|
50
|
+
end
|
51
|
+
|
52
|
+
# check if the path exists
|
53
|
+
def self.config_exists?(config_path)
|
54
|
+
File.exist?(config_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
# When you initialize a client inside a Rails project, it will take the OneSky configuration variables supplied when you called rails generate one_sky:init.
|
58
|
+
# Outside of Rails, credentials are expected to come from environment variables: ONESKY_API_KEY, ONESKY_API_SECRET, ONESKY_PROJECT.
|
59
|
+
# You can override these defaults by providing a hash of options:
|
60
|
+
# * api_key
|
61
|
+
# * api_secret
|
62
|
+
# * project
|
63
|
+
def initialize(options = {})
|
64
|
+
@client = ::OneSky::Client.new(options[:api_key], options[:api_secret])
|
65
|
+
@project = @client.project(options[:project])
|
66
|
+
@platform = @project.platform(options[:platform_id])
|
67
|
+
end
|
68
|
+
|
69
|
+
# Check the configuration of our client.
|
70
|
+
def verify!
|
71
|
+
verify_platform!
|
72
|
+
verify_default_locale!
|
73
|
+
end
|
74
|
+
|
75
|
+
# The default locale for the platform.
|
76
|
+
def platform_base_locale
|
77
|
+
platform_details["base_locale"]
|
78
|
+
end
|
79
|
+
|
80
|
+
# An array of codes. eg. ["en_US", "zh_CN"]
|
81
|
+
def platform_locale_codes
|
82
|
+
platform_locales.map do |hash|
|
83
|
+
hash["locale"]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Cached call to load the locales for a platform.
|
88
|
+
def platform_locales
|
89
|
+
@platform.locales
|
90
|
+
end
|
91
|
+
memoize :platform_locales
|
92
|
+
|
93
|
+
# Cached call to load the details for the platform.
|
94
|
+
def platform_details
|
95
|
+
@platform_details ||= @platform.details
|
96
|
+
end
|
97
|
+
memoize :platform_details
|
98
|
+
|
99
|
+
# Remove all Rails i18n keys as of December 2nd 2011.
|
100
|
+
# https://github.com/svenfuchs/rails-i18n/blob/a4fb3d3dbb1a05a2adc82355c934e81eea67e3a1/rails/locale/en-GB.yml
|
101
|
+
SKIP_KEYS_REGEXP = /^(date|time|support|number|datetime|helpers|errors|activerecord)#{Regexp.escape(I18n.default_separator)}/
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def skip_key?(key)
|
106
|
+
key =~ SKIP_KEYS_REGEXP
|
107
|
+
end
|
108
|
+
|
109
|
+
def upload_phrases(phrases)
|
110
|
+
skip, upload = phrases.partition{ |string_key, string| skip_key?(string_key) }
|
111
|
+
|
112
|
+
puts "Uploading phrases:"
|
113
|
+
puts upload.to_yaml
|
114
|
+
platform.translation.input_phrases(upload)
|
115
|
+
|
116
|
+
puts "Skipped phrases:"
|
117
|
+
puts skip.to_yaml
|
118
|
+
end
|
119
|
+
|
120
|
+
def verify_platform!
|
121
|
+
# call the api for the platform
|
122
|
+
# this'll raise if there's an authentication problem
|
123
|
+
platform_details
|
124
|
+
end
|
125
|
+
|
126
|
+
def verify_default_locale!
|
127
|
+
if I18n.default_locale.to_s.downcase != locale_os_to_i18n(platform_base_locale).to_s.downcase
|
128
|
+
raise DefaultLocaleMismatchError, "I18n and OneSky have different default locale settings. #{I18n.default_locale} <> #{platform_base_locale}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# i18n has a default locale of :en
|
133
|
+
# while OneSky uses "en_US"
|
134
|
+
def locale_os_to_i18n(locale)
|
135
|
+
case locale
|
136
|
+
when "en_US"
|
137
|
+
"en"
|
138
|
+
else
|
139
|
+
locale
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def locale_i18n_to_os(locale)
|
144
|
+
case locale.to_s
|
145
|
+
when "en"
|
146
|
+
"en_US"
|
147
|
+
else
|
148
|
+
locale.to_s
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
namespace :one_sky do
|
2
|
+
|
3
|
+
desc "Upload phrases for translation to OneSky."
|
4
|
+
task :upload => :environment do
|
5
|
+
simple_client.upload(locales_path)
|
6
|
+
puts "Phrases uploaded to OneSky. Please ask your translators to... well... get translating."
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Download available translations from OneSky and store as yml files."
|
10
|
+
task :download => :environment do
|
11
|
+
simple_client.download(locales_path)
|
12
|
+
puts "Translations downloaded and saved to config/locales/*_one_sky.yml files."
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :active_record do
|
16
|
+
|
17
|
+
desc "Upload."
|
18
|
+
task :upload => :environment do
|
19
|
+
active_record_client.upload
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Download available translations from OneSky and stores into Active Record database"
|
23
|
+
task :download => :environment do
|
24
|
+
active_record_client.download
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def active_record_client
|
30
|
+
I18n::OneSky::ActiveRecordClient.from_config(one_sky_config)
|
31
|
+
end
|
32
|
+
|
33
|
+
def simple_client
|
34
|
+
I18n::OneSky::SimpleClient.from_config(one_sky_config)
|
35
|
+
end
|
36
|
+
|
37
|
+
def locales_path
|
38
|
+
Rails.root.join("config/locales")
|
39
|
+
end
|
40
|
+
|
41
|
+
def one_sky_config
|
42
|
+
Rails.root.join('config', 'one_sky.yml')
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'i18n/one_sky/client_base'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
module OneSky
|
6
|
+
# A class to deal with the OneSky apis
|
7
|
+
# it encapsulates the logic of I18n::Backend::ActiveRecord
|
8
|
+
class SimpleClient < ClientBase
|
9
|
+
include I18n::Backend::Flatten
|
10
|
+
|
11
|
+
# Store all translations from OneSky in YAMl files.
|
12
|
+
def download(yaml_path)
|
13
|
+
platform_locales.each do |locale|
|
14
|
+
locale_code = locale["locale"]
|
15
|
+
local_name = locale["name"]["local"]
|
16
|
+
english_name = locale["name"]["eng"]
|
17
|
+
|
18
|
+
if locale_code == platform_base_locale
|
19
|
+
# We skip the base locale.
|
20
|
+
next
|
21
|
+
else
|
22
|
+
yaml = platform.translation.download_yaml(locale_code)
|
23
|
+
|
24
|
+
File.open(File.join(yaml_path, "#{locale_code}_one_sky.yml"), "w") do |f|
|
25
|
+
f.puts "# PLEASE DO NOT EDIT THIS FILE."
|
26
|
+
f.puts "# This was downloaded from OneSky. Log in to your OneSky account to manage translations on their website."
|
27
|
+
f.puts "# Language code: #{locale_code}"
|
28
|
+
f.puts "# Language name: #{local_name}"
|
29
|
+
f.puts "# Language English name: #{english_name}"
|
30
|
+
f.write yaml
|
31
|
+
|
32
|
+
puts "Writing: #{f.path}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Scan all yaml files for keys in the default locale, and push them to OneSky.
|
39
|
+
def upload(yaml_path)
|
40
|
+
upload_phrases(all_phrases(yaml_path))
|
41
|
+
end
|
42
|
+
|
43
|
+
def all_phrases(yaml_path)
|
44
|
+
phrases = {}
|
45
|
+
Dir.glob("#{yaml_path}/**/*.yml").each do |path|
|
46
|
+
hash = YAML::load(File.read(path))
|
47
|
+
phrases.merge!(hash[I18n.default_locale.to_s]) if hash.has_key?(I18n.default_locale.to_s)
|
48
|
+
end
|
49
|
+
flatten_phrases(phrases)
|
50
|
+
end
|
51
|
+
memoize :all_phrases
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def flatten_phrases(phrases)
|
56
|
+
hash = {}
|
57
|
+
flatten_keys(phrases, true) do |key, value|
|
58
|
+
hash[key.to_s] = value unless value.is_a?(Hash)
|
59
|
+
end
|
60
|
+
hash
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# this spec runs through live api calls
|
4
|
+
# and requires a real api key for the account
|
5
|
+
#
|
6
|
+
# http://ruby-gem-tests.oneskyapp.com/
|
7
|
+
#
|
8
|
+
# before running this test we need to do
|
9
|
+
#
|
10
|
+
# export ONESKY_API_KEY="the key"
|
11
|
+
# export ONESKY_API_SECRET="the secret"
|
12
|
+
#
|
13
|
+
# the rake spec task skips these test
|
14
|
+
# you need to run
|
15
|
+
#
|
16
|
+
# rake spec:live
|
17
|
+
#
|
18
|
+
require 'spec_helper'
|
19
|
+
|
20
|
+
require 'active_record'
|
21
|
+
|
22
|
+
ActiveRecord::Base.establish_connection(
|
23
|
+
:adapter => (RUBY_PLATFORM=="java" ? "jdbcsqlite3" : "sqlite3"),
|
24
|
+
:database => ":memory:"
|
25
|
+
)
|
26
|
+
|
27
|
+
ActiveRecord::Schema.define(:version => 0) do
|
28
|
+
create_table :translations, :force => true do |t|
|
29
|
+
t.string :locale
|
30
|
+
t.string :key
|
31
|
+
t.text :value
|
32
|
+
t.text :interpolations
|
33
|
+
t.boolean :is_proc, :default => false
|
34
|
+
|
35
|
+
t.timestamps
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe I18n::OneSky::ActiveRecordClient, "LIVE", :live => true do
|
40
|
+
|
41
|
+
let(:onesky_api_key) { ENV["ONESKY_API_KEY"] }
|
42
|
+
let(:onesky_api_secret) { ENV["ONESKY_API_SECRET"] }
|
43
|
+
let(:project_name) { "api-test" }
|
44
|
+
let(:platform_id) { 840 }
|
45
|
+
let(:platform_code) { "website" }
|
46
|
+
|
47
|
+
let(:english_locale) { "en_US" }
|
48
|
+
let(:chinese_locale) { "zh_CN" }
|
49
|
+
|
50
|
+
let(:client) do
|
51
|
+
I18n::OneSky::ActiveRecordClient.new(
|
52
|
+
:api_key => onesky_api_key,
|
53
|
+
:api_secret => onesky_api_secret,
|
54
|
+
:project => project_name,
|
55
|
+
:platform_id => platform_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
I18n.backend = I18n::Backend::ActiveRecord.new
|
60
|
+
end
|
61
|
+
|
62
|
+
context "download" do
|
63
|
+
|
64
|
+
it "works" do
|
65
|
+
client.download
|
66
|
+
end
|
67
|
+
|
68
|
+
context "with a chained backend" do
|
69
|
+
before(:each) do
|
70
|
+
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n::Backend::ActiveRecord.new)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "works" do
|
74
|
+
client.upload
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
context "upload" do
|
81
|
+
|
82
|
+
before(:each) do
|
83
|
+
I18n::Backend::ActiveRecord::Translation.delete_all
|
84
|
+
I18n::Backend::ActiveRecord::Translation.create!(:locale => "en", :key => "test1", :value => "Test 1")
|
85
|
+
I18n::Backend::ActiveRecord::Translation.create!(:locale => "en", :key => "test2", :value => "Test 2")
|
86
|
+
I18n::Backend::ActiveRecord::Translation.create!(:locale => "en", :key => "number.something", :value => "skip this")
|
87
|
+
end
|
88
|
+
|
89
|
+
it "works" do
|
90
|
+
client.upload
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with a chained backend" do
|
94
|
+
before(:each) do
|
95
|
+
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n::Backend::ActiveRecord.new)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "works" do
|
99
|
+
client.upload
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
File without changes
|
data/spec/simple_client_spec.rb
CHANGED
@@ -1,58 +1,82 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
|
-
|
3
|
+
# this spec runs through live api calls
|
4
|
+
# and requires a real api key for the account
|
5
|
+
#
|
6
|
+
# http://ruby-gem-tests.oneskyapp.com/
|
7
|
+
#
|
8
|
+
# before running this test we need to do
|
9
|
+
#
|
10
|
+
# export ONESKY_API_KEY="the key"
|
11
|
+
# export ONESKY_API_SECRET="the secret"
|
12
|
+
#
|
13
|
+
# the rake spec task skips these test
|
14
|
+
# you need to run
|
15
|
+
#
|
16
|
+
# rake spec:live
|
17
|
+
#
|
18
|
+
require 'spec_helper'
|
19
|
+
require 'tmpdir'
|
20
|
+
require 'yaml'
|
4
21
|
|
5
|
-
|
6
|
-
|
22
|
+
describe I18n::OneSky::SimpleClient, "LIVE", :live => true do
|
23
|
+
|
24
|
+
let(:onesky_api_key) { ENV["ONESKY_API_KEY"] }
|
25
|
+
let(:onesky_api_secret) { ENV["ONESKY_API_SECRET"] }
|
26
|
+
let(:project_name) { "api-test" }
|
27
|
+
let(:platform_id) { 840 }
|
28
|
+
let(:platform_code) { "website" }
|
29
|
+
|
30
|
+
let(:english_locale) { "en_US" }
|
31
|
+
let(:chinese_locale) { "zh_CN" }
|
32
|
+
|
33
|
+
let(:client) do
|
34
|
+
I18n::OneSky::SimpleClient.new(
|
35
|
+
:api_key => onesky_api_key,
|
36
|
+
:api_secret => onesky_api_secret,
|
37
|
+
:project => project_name,
|
38
|
+
:platform_id => platform_id)
|
7
39
|
end
|
40
|
+
|
41
|
+
context "download" do
|
8
42
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "SimpleClient" do
|
16
|
-
include I18nOneSkySpecHelpers
|
17
|
-
|
18
|
-
before do
|
19
|
-
@client = create_simple_client_and_load
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "#load_phrases" do
|
23
|
-
it "should load nested phrases." do
|
24
|
-
@client.phrases_nested[:my_pages][:page][:title].should == "My Page Title"
|
43
|
+
let(:yaml_path) { Dir.tmpdir }
|
44
|
+
|
45
|
+
def yaml_files
|
46
|
+
Dir.glob(yaml_path+"/*.yml")
|
25
47
|
end
|
26
48
|
|
27
|
-
|
28
|
-
|
49
|
+
before(:each) do
|
50
|
+
# delete any pre-existing yml files.
|
51
|
+
File.delete(*yaml_files)
|
29
52
|
end
|
30
53
|
|
31
|
-
it "
|
32
|
-
|
54
|
+
it "creates yaml files" do
|
55
|
+
yaml_files.should be_empty
|
56
|
+
|
57
|
+
client.download(yaml_path)
|
58
|
+
|
59
|
+
yaml_files.should_not be_empty
|
33
60
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
61
|
+
|
62
|
+
it "creates a yaml file for the chinese locale." do
|
63
|
+
client.download(yaml_path)
|
64
|
+
|
65
|
+
chinese_file = yaml_files.detect{|f| f.end_with?("#{chinese_locale}_one_sky.yml") }
|
66
|
+
yaml = YAML.load(File.read(chinese_file))
|
67
|
+
yaml.keys.should == [chinese_locale]
|
39
68
|
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe "SimpleClient" do
|
44
|
-
include I18nOneSkySpecHelpers
|
45
69
|
|
46
|
-
before do
|
47
|
-
@client = create_simple_client
|
48
70
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
71
|
+
|
72
|
+
context "upload" do
|
73
|
+
|
74
|
+
let(:yaml_path) { File.expand_path("../fixtures/files", __FILE__) }
|
75
|
+
|
76
|
+
it "uploads any yaml files in the path" do
|
77
|
+
client.upload(yaml_path)
|
55
78
|
end
|
56
79
|
end
|
57
|
-
|
58
|
-
|
80
|
+
|
81
|
+
|
82
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-one_sky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -15,7 +15,7 @@ date: 2011-12-07 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: i18n
|
18
|
-
requirement: &
|
18
|
+
requirement: &70239195965320 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,43 +23,43 @@ dependencies:
|
|
23
23
|
version: 0.5.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70239195965320
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: one_sky
|
29
|
-
requirement: &
|
29
|
+
requirement: &70239195960480 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - =
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 2.0.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70239195960480
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: i18n-active_record
|
40
|
-
requirement: &
|
40
|
+
requirement: &70239203730000 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 0.0.2
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70239203730000
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
51
|
-
requirement: &
|
50
|
+
name: activesupport
|
51
|
+
requirement: &70239203729540 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - ! '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 2.2.2
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70239203729540
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: rspec
|
62
|
-
requirement: &
|
62
|
+
requirement: &70239203729080 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ~>
|
@@ -67,18 +67,18 @@ dependencies:
|
|
67
67
|
version: 2.2.0
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70239203729080
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: bundler
|
73
|
-
requirement: &
|
73
|
+
requirement: &70239203728620 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
|
-
- -
|
76
|
+
- - ! '>='
|
77
77
|
- !ruby/object:Gem::Version
|
78
78
|
version: 1.0.0
|
79
79
|
type: :development
|
80
80
|
prerelease: false
|
81
|
-
version_requirements: *
|
81
|
+
version_requirements: *70239203728620
|
82
82
|
description: A set of I18n extensions that use OneSky. At its most basic, this allows
|
83
83
|
you to easily submit translation requests to the OneSky service and download available
|
84
84
|
translations as Simple backend YAML files.
|
@@ -91,6 +91,7 @@ extensions: []
|
|
91
91
|
extra_rdoc_files: []
|
92
92
|
files:
|
93
93
|
- .gitignore
|
94
|
+
- .rspec
|
94
95
|
- CHANGELOG
|
95
96
|
- CREDITS
|
96
97
|
- Gemfile
|
@@ -101,16 +102,20 @@ files:
|
|
101
102
|
- i18n-one_sky.gemspec
|
102
103
|
- lib/generators/one_sky/init/init_generator.rb
|
103
104
|
- lib/generators/one_sky/init_active_record_backend/init_active_record_backend_generator.rb
|
105
|
+
- lib/generators/one_sky/init_active_record_backend/templates/active_record_backend.rb
|
104
106
|
- lib/generators/one_sky/init_active_record_backend/templates/migration.rb
|
105
|
-
- lib/generators/one_sky/init_active_record_backend/templates/onesky.rb
|
106
107
|
- lib/i18n-one_sky.rb
|
107
|
-
- lib/i18n
|
108
|
-
- lib/i18n
|
109
|
-
- lib/i18n
|
110
|
-
- lib/i18n
|
111
|
-
-
|
112
|
-
-
|
108
|
+
- lib/i18n/one_sky.rb
|
109
|
+
- lib/i18n/one_sky/active_record_client.rb
|
110
|
+
- lib/i18n/one_sky/client_base.rb
|
111
|
+
- lib/i18n/one_sky/rails/railtie.rb
|
112
|
+
- lib/i18n/one_sky/rails/tasks/i18n-one_sky.rake
|
113
|
+
- lib/i18n/one_sky/simple_client.rb
|
114
|
+
- lib/i18n/one_sky/version.rb
|
115
|
+
- spec/active_record_client_spec.rb
|
116
|
+
- spec/fixtures/files/en.yml
|
113
117
|
- spec/simple_client_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
114
119
|
homepage: http://rubygems.org/gems/i18n-one_sky
|
115
120
|
licenses: []
|
116
121
|
post_install_message:
|
@@ -136,7 +141,8 @@ signing_key:
|
|
136
141
|
specification_version: 3
|
137
142
|
summary: I18n extensions using OneSky -- the community-powered translation service.
|
138
143
|
test_files:
|
139
|
-
- spec/
|
140
|
-
- spec/
|
144
|
+
- spec/active_record_client_spec.rb
|
145
|
+
- spec/fixtures/files/en.yml
|
141
146
|
- spec/simple_client_spec.rb
|
147
|
+
- spec/spec_helper.rb
|
142
148
|
has_rdoc:
|
@@ -1,24 +0,0 @@
|
|
1
|
-
namespace :one_sky do
|
2
|
-
desc "Upload phrases for translation to OneSky."
|
3
|
-
task :upload_phrases => :environment do
|
4
|
-
client = I18n::OneSky::SimpleClient.new
|
5
|
-
puts "Default locale for this Rails app is: #{I18n.default_locale}"
|
6
|
-
puts client.load_phrases
|
7
|
-
client.upload_phrases
|
8
|
-
puts "Phrases uploaded to OneSky. Please ask your translators to... well... get translating."
|
9
|
-
end
|
10
|
-
|
11
|
-
desc "Download available translations from OneSky and store as yml files."
|
12
|
-
task :download_translations do
|
13
|
-
client = I18n::OneSky::SimpleClient.new
|
14
|
-
client.download_translations
|
15
|
-
puts "Translations downloaded and saved to config/locales/*_one_sky.yml files."
|
16
|
-
end
|
17
|
-
|
18
|
-
desc "Download available translations from OneSky and stores into Active Record database"
|
19
|
-
task :update_activerecord_translations do
|
20
|
-
client = I18n::OneSky::SimpleClient.new
|
21
|
-
client.download_translations(nil, true, true)
|
22
|
-
puts "Translations downloaded and saved to database."
|
23
|
-
end
|
24
|
-
end
|
@@ -1,162 +0,0 @@
|
|
1
|
-
module I18n
|
2
|
-
module OneSky
|
3
|
-
# This class is the bridge between the OneSky service and the I18n Simple backend.
|
4
|
-
# It takes the phrases defined in I18n's default locale and uploads them to OneSky for translation.
|
5
|
-
# Then it downloads available translations and saves them as Simple backend's YAML files.
|
6
|
-
# A regular workflow would then look like:
|
7
|
-
# initialize -> load_phrases -> upload_phrases -> download_translations
|
8
|
-
class SimpleClient
|
9
|
-
include I18n::Backend::Flatten
|
10
|
-
|
11
|
-
attr_reader :phrases_nested, :phrases_flat
|
12
|
-
# The base OneSky project. Gives you low-level access to the API gem.
|
13
|
-
attr_reader :project
|
14
|
-
|
15
|
-
# When you initialize a client inside a Rails project, it will take the OneSky configuration variables supplied when you called rails generate one_sky:init.
|
16
|
-
# Outside of Rails, credentials are expected to come from environment variables: ONESKY_API_KEY, ONESKY_API_SECRET, ONESKY_PROJECT.
|
17
|
-
# You can override these defaults by providing a hash of options:
|
18
|
-
# * api_key
|
19
|
-
# * api_secret
|
20
|
-
# * project
|
21
|
-
def initialize(options = {})
|
22
|
-
options = default_options.merge!(options)
|
23
|
-
@project = ::OneSky::Project.new(options[:api_key], options[:api_secret], options[:project])
|
24
|
-
#@one_sky_locale = @project.details["base_locale"].gsub('_', '-')
|
25
|
-
@one_sky_locale = @project.details["base_locale"]
|
26
|
-
check_default_locales_match
|
27
|
-
@one_sky_languages = @project.languages
|
28
|
-
end
|
29
|
-
|
30
|
-
# This will load the phrases defined for I18n's default locale.
|
31
|
-
# If not a Rails project, manually supply the path where the I18n yml or rb files for located.
|
32
|
-
def load_phrases(path=nil)
|
33
|
-
backend = I18n.backend.is_a?(I18n::Backend::Chain) ? I18n.backend.backends.last : I18n.backend
|
34
|
-
|
35
|
-
if defined?(Rails)
|
36
|
-
backend.load_translations
|
37
|
-
else
|
38
|
-
raise ArgumentError, "Please supply the path where locales are located." unless path
|
39
|
-
path = path.chop if path =~ /\/$/
|
40
|
-
backend.load_translations(*Dir.glob("#{path}/**/*.{yml,rb}"))
|
41
|
-
end
|
42
|
-
|
43
|
-
@phrases_nested = backend.instance_variable_get("@translations")[I18n.default_locale]
|
44
|
-
|
45
|
-
# Flatten the nested hash.
|
46
|
-
flat_keys = flatten_translations(I18n.default_locale, @phrases_nested, true, false)
|
47
|
-
|
48
|
-
# Remove those "supporting/generic" i18n entities that we're not sending to OneSky.
|
49
|
-
# Those that are found in the rails-i18n github repository.
|
50
|
-
# Eg. number, datetime, activemodel, etc.
|
51
|
-
# Note: This doesn't handle FLATTEN_SEPARATOR other than '.' yet.
|
52
|
-
patterns = %w{number datetime activemodel support activerecord date time errors helpers}.inject([]) { |o,e| o << Regexp.new("^#{e}(\\..*)?$") }
|
53
|
-
@phrases_flat = flat_keys.reject { |k,v| patterns.find { |e| k.to_s =~ e } }
|
54
|
-
end
|
55
|
-
|
56
|
-
# Once you've loaded the default locale's phrases, call this method to send them to OneSky for translation.
|
57
|
-
def upload_phrases
|
58
|
-
load_phrases unless @phrases_flat
|
59
|
-
|
60
|
-
batch_requests = @phrases_flat.inject([]) do |o,(k,v)|
|
61
|
-
# ToDo: Materialize ALL CLDR plural tags if at least one is present for a leaf node.
|
62
|
-
o << {:string_key => k, :string => v}
|
63
|
-
end
|
64
|
-
|
65
|
-
@project.input_bulk(batch_requests)
|
66
|
-
end
|
67
|
-
|
68
|
-
# When your translators are done, call this method to download all available translations and save them as Simple backend *.yml files.
|
69
|
-
# Outside of Rails, manually supply the path where downloaded files should be saved.
|
70
|
-
def download_translations(path=nil, download_base_locale=false, use_active_record=false)
|
71
|
-
if defined?(Rails)
|
72
|
-
path ||= [Rails.root.to_s, "config", "locales"].join("/")
|
73
|
-
else
|
74
|
-
raise ArgumentError, "Please supply the path where locales are to be downloaded." unless path
|
75
|
-
path = path.chop if path =~ /\/$/
|
76
|
-
end
|
77
|
-
|
78
|
-
output = @project.output
|
79
|
-
|
80
|
-
# Let's ignore other hash nodes from the API and just rely on the string keys we sent during upload. Prefix with locale.
|
81
|
-
@translations = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
|
82
|
-
output.map do |k0,v0| # Page level
|
83
|
-
v0.map do |k1, v1| # Locale level
|
84
|
-
v1.map do |k2, v2| # string key level
|
85
|
-
@translations[k1][[k1, k2].join('.')] = v2
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
if use_active_record
|
91
|
-
@translations.map { |k,v| save_locale(k, v) unless (k.to_s == @one_sky_locale and !download_base_locale)}
|
92
|
-
else
|
93
|
-
# Delete all existing one_sky translation files before downloading a new set.
|
94
|
-
File.delete(*Dir.glob("#{path}/*_one_sky.yml"))
|
95
|
-
|
96
|
-
# Process each locale and save to file
|
97
|
-
@translations.map { |k,v| save_locale(k, v, :filename => "#{path}/#{k}_one_sky.yml") unless (k.to_s == @one_sky_locale and !download_base_locale)}
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
protected
|
102
|
-
|
103
|
-
def save_locale(lang_code, phrases, options={})
|
104
|
-
nested = to_nested_nodes(phrases)
|
105
|
-
|
106
|
-
lang = @one_sky_languages.find { |e| e["locale"] == lang_code }
|
107
|
-
|
108
|
-
if options[:filename]
|
109
|
-
filename = options[:filename]
|
110
|
-
File.open(filename, 'w') do |f|
|
111
|
-
f.puts "# PLEASE DO NOT EDIT THIS FILE."
|
112
|
-
f.puts "# This was downloaded from OneSky. Log in to your OneSky account to manage translations on their website."
|
113
|
-
f.puts "# Language code: #{lang['locale']}"
|
114
|
-
f.puts "# Language name: #{lang['local_name']}"
|
115
|
-
f.puts "# Language English name: #{lang['eng_name']}"
|
116
|
-
f.print(nested.to_yaml)
|
117
|
-
end
|
118
|
-
filename
|
119
|
-
else
|
120
|
-
|
121
|
-
lang = @one_sky_languages.find { |e| e["locale"] == lang_code }
|
122
|
-
|
123
|
-
nested.each do |k, values|
|
124
|
-
values.each do |value|
|
125
|
-
I18n.backend.store_translations(k, value[0] => value[1])
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def to_nested_nodes(phrases)
|
132
|
-
nested = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
|
133
|
-
phrases.each do |k,v|
|
134
|
-
node = nested
|
135
|
-
parts = k.split('.')
|
136
|
-
parts.each_with_index { |segment,i| node[segment]; i == parts.size - 1 ? node[segment] = v : node = node[segment] }
|
137
|
-
end
|
138
|
-
|
139
|
-
nested
|
140
|
-
end
|
141
|
-
|
142
|
-
def default_options
|
143
|
-
options = {:api_key => ENV["ONESKY_API_KEY"], :api_secret => ENV["ONESKY_API_SECRET"], :project => ENV["ONESKY_PROJECT"]}
|
144
|
-
|
145
|
-
if defined?(Rails)
|
146
|
-
config_file = [Rails.root.to_s, 'config', 'one_sky.yml'].join('/')
|
147
|
-
|
148
|
-
options = YAML.load_file(config_file).symbolize_keys if File.exists?(config_file)
|
149
|
-
end
|
150
|
-
|
151
|
-
options
|
152
|
-
end
|
153
|
-
|
154
|
-
def check_default_locales_match
|
155
|
-
# Special case: i18n "en" is "en-us".
|
156
|
-
i18n_default_locale = I18n.default_locale == :en ? "en_us" : I18n.default_locale.to_s.downcase
|
157
|
-
raise DefaultLocaleMismatchError, "I18n and OneSky have different default locale settings. #{I18n.default_locale.to_s} <> #{@one_sky_locale}" if i18n_default_locale != @one_sky_locale.downcase
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
data/spec/helpers.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
$:.unshift File.expand_path('..', __FILE__)
|
2
|
-
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
-
|
4
|
-
require 'i18n-one_sky'
|
5
|
-
|
6
|
-
module I18nOneSkySpecHelpers
|
7
|
-
def create_simple_client
|
8
|
-
raise "Please set environment variables: ONESKY_API_KEY, ONESKY_API_SECRET and ONESKY_SPEC_PROJ (default: i18noneskyspec) before running spec." unless [ENV["ONESKY_API_KEY"], ENV["ONESKY_API_SECRET"]].all?
|
9
|
-
I18n.default_locale = :en
|
10
|
-
client = I18n::OneSky::SimpleClient.new(
|
11
|
-
:api_key => ENV["ONESKY_API_KEY"],
|
12
|
-
:api_secret => ENV["ONESKY_API_SECRET"],
|
13
|
-
:project => ENV["ONESKY_SPEC_PROJ"] || "i18noneskyspec"
|
14
|
-
)
|
15
|
-
end
|
16
|
-
|
17
|
-
def create_simple_client_and_load
|
18
|
-
client = create_simple_client
|
19
|
-
client.load_phrases([File.dirname(__FILE__), "data"].join('/'))
|
20
|
-
client
|
21
|
-
end
|
22
|
-
end
|