i18n-one_sky 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|