gettext-one_sky 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/CHANGELOG +5 -0
- data/CREDITS +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +40 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +131 -0
- data/Rakefile +13 -0
- data/gettext-one_sky.gemspec +28 -0
- data/lib/generators/one_sky/init/init_generator.rb +30 -0
- data/lib/gettext-one_sky.rb +10 -0
- data/lib/gettext-one_sky/my_po_data.rb +44 -0
- data/lib/gettext-one_sky/my_po_parser.rb +103 -0
- data/lib/gettext-one_sky/rails/railtie.rb +9 -0
- data/lib/gettext-one_sky/rails/tasks/gettext-one_sky.rake +31 -0
- data/lib/gettext-one_sky/simple_client.rb +175 -0
- data/lib/gettext-one_sky/version.rb +5 -0
- data/spec/end_to_end_spec.rb +27 -0
- data/spec/helpers.rb +64 -0
- data/spec/po/en_US/simple_client.po +53 -0
- data/spec/po/simple_client.pot +54 -0
- data/spec/simple_client_spec.rb +142 -0
- metadata +172 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
data/CREDITS
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gettext-one_sky (0.0.1)
|
5
|
+
gettext (~> 0.5.0)
|
6
|
+
one_sky (~> 0.0.2)
|
7
|
+
module GetText (~> 0.14.4)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
diff-lcs (1.1.2)
|
13
|
+
gettext (0.5.0)
|
14
|
+
json (1.4.6)
|
15
|
+
mime-types (1.16)
|
16
|
+
one_sky (0.0.2)
|
17
|
+
json (~> 1.4.6)
|
18
|
+
rest-client (~> 1.6.1)
|
19
|
+
rest-client (1.6.1)
|
20
|
+
mime-types (>= 1.16)
|
21
|
+
rspec (2.2.0)
|
22
|
+
rspec-core (~> 2.2)
|
23
|
+
rspec-expectations (~> 2.2)
|
24
|
+
rspec-mocks (~> 2.2)
|
25
|
+
rspec-core (2.2.1)
|
26
|
+
rspec-expectations (2.2.0)
|
27
|
+
diff-lcs (~> 1.1.2)
|
28
|
+
rspec-mocks (2.2.0)
|
29
|
+
module GetText (0.14.6)
|
30
|
+
|
31
|
+
PLATFORMS
|
32
|
+
ruby
|
33
|
+
|
34
|
+
DEPENDENCIES
|
35
|
+
bundler (~> 1.0.0)
|
36
|
+
gettext (~> 0.5.0)
|
37
|
+
gettext-one_sky!
|
38
|
+
one_sky (~> 0.0.2)
|
39
|
+
rspec (~> 2.2.0)
|
40
|
+
module GetText (~> 0.14.4)
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010-2011 {OneSky, Inc.}[link:http://www.oneskyapp.com]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUmodule GetTextS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
= Gettext OneSky
|
2
|
+
|
3
|
+
|
4
|
+
OneSky[link:http://www.oneskyapp.com] is a new service that lets developers reach a global audience by easily enabling them to translate their websites and applications to different languages through the help of the community.
|
5
|
+
|
6
|
+
This gem integrates OneSky and gettext. At its most basic, it allows you to take the phrases defined under gettext .pot file and upload it to OneSky[link:http://www.oneskyapp.com] for translation by the community. Afterwards, you can download available translations and save them as .po files.
|
7
|
+
|
8
|
+
This gem is supporting Ruby projects using gettext gem to handle localization. If you are using i18n, checkout i18n-one_sky gem
|
9
|
+
|
10
|
+
|
11
|
+
= PO file support
|
12
|
+
|
13
|
+
1. One layer of Context
|
14
|
+
2. Text Domain as page
|
15
|
+
3. Reserved Context: Singular, Plural and General
|
16
|
+
|
17
|
+
|
18
|
+
--- One layer of Context
|
19
|
+
|
20
|
+
Onesky currently only support 1 layer of context. That means only either "msgctxt" / "msgstr[0]" / "msgstr[1]" will be supported but not both.
|
21
|
+
|
22
|
+
|
23
|
+
--- Text Domain as page
|
24
|
+
|
25
|
+
Regarding the text domain, please use the file name as the page parameter. That means if the po file is abc.po, just add the string with parameter page=abc.po.
|
26
|
+
|
27
|
+
|
28
|
+
--- Reserved Context: Singular, Plural and General
|
29
|
+
|
30
|
+
"Singular" / "Plural" / "General" are reserved context words.
|
31
|
+
|
32
|
+
Onesky only support "Singular" and "Plural" for po files. That means only [0] and [1] are used.
|
33
|
+
Which will return in result:
|
34
|
+
|
35
|
+
{"key": { "Singular": "Word", "Plural": "Words"}}
|
36
|
+
|
37
|
+
For the stuff without context, you may use "General" if there are other strings with same string key but different context:
|
38
|
+
|
39
|
+
{"key_of_book": { "General": "book", "verb": "book", "noun": "book"}}
|
40
|
+
|
41
|
+
|
42
|
+
= Using inside a Rails project
|
43
|
+
|
44
|
+
1. Generate OneSky API key
|
45
|
+
2. Generate .pot
|
46
|
+
3. Upload .pot to OneSky
|
47
|
+
4. Upload translated .po to OneSky
|
48
|
+
5. Download latest translated files .po from OneSky
|
49
|
+
6. Overwrite old .po files
|
50
|
+
7. Generate .mo files
|
51
|
+
|
52
|
+
|
53
|
+
--- Generate OneSky API key
|
54
|
+
|
55
|
+
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:
|
56
|
+
|
57
|
+
rails generate one_sky:init my_api_key my_api_secret my_project
|
58
|
+
|
59
|
+
This will create the configuration file config/one_sky.yml.
|
60
|
+
|
61
|
+
|
62
|
+
--- Generate .pot
|
63
|
+
|
64
|
+
Use the gettext rake task
|
65
|
+
|
66
|
+
rake updatepo
|
67
|
+
|
68
|
+
|
69
|
+
--- Upload .pot to OneSky
|
70
|
+
|
71
|
+
So assuming that you already have your .pot file generated, it's time now to submit these phrases to OneSky:
|
72
|
+
|
73
|
+
rake one_sky:upload_phrases
|
74
|
+
|
75
|
+
|
76
|
+
--- Upload translated .po to OneSky
|
77
|
+
|
78
|
+
You may have some translated .po files in your repository. Upload them to Onesky:
|
79
|
+
|
80
|
+
rake one_sky:upload_translated_phrases
|
81
|
+
|
82
|
+
|
83
|
+
--- Download latest translated files .po from OneSky
|
84
|
+
|
85
|
+
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:
|
86
|
+
|
87
|
+
rake one_sky:download_translations
|
88
|
+
|
89
|
+
This will save the translations inside po/**/from_one_sky.po files.
|
90
|
+
|
91
|
+
|
92
|
+
--- Overwrite old .po files
|
93
|
+
|
94
|
+
Overwrite your own .po files by the downloaded from_one_sky.po file.
|
95
|
+
|
96
|
+
|
97
|
+
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.
|
98
|
+
|
99
|
+
|
100
|
+
= Using outside Rails
|
101
|
+
|
102
|
+
The steps are similar. Install it like any regular gem:
|
103
|
+
|
104
|
+
gem install gettext-one_sky
|
105
|
+
|
106
|
+
And see the gettext-one_sky.rake and GetText::OneSky::SimpleClient for the methods available in Ruby.
|
107
|
+
|
108
|
+
|
109
|
+
= TODO
|
110
|
+
|
111
|
+
* merge downloaded translation with .pot to generate the .po files
|
112
|
+
* upload existing .po files to onesky service
|
113
|
+
* handle textdomain.po
|
114
|
+
|
115
|
+
|
116
|
+
= History
|
117
|
+
|
118
|
+
See CHANGELOG[link:CHANGELOG.html]
|
119
|
+
|
120
|
+
|
121
|
+
= Credits
|
122
|
+
|
123
|
+
See CREDITS[link:CREDITS.html]
|
124
|
+
|
125
|
+
|
126
|
+
= License
|
127
|
+
|
128
|
+
Copyright 2010-2011 {OneSky, Inc.}[link:http://www.oneskyapp.com]
|
129
|
+
|
130
|
+
Licensed under the {MIT License}[link:MIT-LICENSE.html].
|
131
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
# = RDoc
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
Rake::RDocTask.new do |t|
|
8
|
+
t.rdoc_dir = 'rdoc'
|
9
|
+
t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
10
|
+
t.options << '--charset' << 'utf-8'
|
11
|
+
t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'CHANGELOG', 'CREDITS', 'lib/**/*.rb')
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "gettext-one_sky/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "gettext-one_sky"
|
7
|
+
s.version = GetText::Onesky::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Eddie Lau"]
|
10
|
+
s.email = ["tatonlto@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/gettext-one_sky"
|
12
|
+
s.summary = %q{gettext extensions using OneSky -- the community-powered translation service.}
|
13
|
+
s.description = %q{This is a backport of i18n-one_sky-ruby to support gettext. i18n is not included in Rails before Rails 2.2. This gem handles the downloading and uploading translation files (.po) to Onesky server by calling Onesky API.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "gettext-one_sky"
|
16
|
+
|
17
|
+
s.add_dependency "gettext", "~> 2.0.0"
|
18
|
+
s.add_dependency "one_sky", "~> 0.0.2"
|
19
|
+
s.add_dependency "thor", "~> 0.14.4"
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec", "~> 2.2.0"
|
22
|
+
s.add_development_dependency "bundler", "~> 1.0.0"
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module OneSky
|
2
|
+
module Generators
|
3
|
+
class InitGenerator < ::Rails::Generators::Base
|
4
|
+
desc "This generator configures gettext-one_sky for use on this Rails project."
|
5
|
+
argument :api_key, :type => :string, :desc => "The API key you got from OneSky"
|
6
|
+
argument :api_secret, :type => :string, :desc => "The API secret you got from OneSky"
|
7
|
+
argument :project, :type => :string, :desc => "The name of the OneSky project"
|
8
|
+
class_option :force, :type => :boolean, :default => false, :desc => "Overwrite if config file already exists"
|
9
|
+
@@config_file = [Rails.root.to_s, 'config', 'one_sky.yml'].join('/')
|
10
|
+
|
11
|
+
def remove_config_file
|
12
|
+
if File.exists? @@config_file
|
13
|
+
if options.force?
|
14
|
+
say_status("warning", "config file already exists and is being overwritten.", :yellow)
|
15
|
+
remove_file @@config_file
|
16
|
+
else
|
17
|
+
say_status("error", "config file already exists. Use --force to overwrite.", :red)
|
18
|
+
raise "Error: OneSky config file exists."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_config_file
|
24
|
+
config_hash = {"api_key" => api_key, "api_secret" => api_secret, "project" => project}
|
25
|
+
create_file(@@config_file, config_hash.to_yaml)
|
26
|
+
say_status("info", "config file #{@@config_file} created.", :green)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'gettext'
|
2
|
+
require 'one_sky'
|
3
|
+
require 'gettext-one_sky/rails/railtie.rb' if defined? Rails
|
4
|
+
|
5
|
+
module GetText
|
6
|
+
module OneSky
|
7
|
+
autoload :SimpleClient, 'gettext-one_sky/simple_client'
|
8
|
+
class DefaultLocaleMismatchError < StandardError; end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module GetText
|
2
|
+
module OneSky
|
3
|
+
class MyPoData < GetText::RMsgMerge::PoData
|
4
|
+
|
5
|
+
def generate_po_entry(msgid)
|
6
|
+
str = ""
|
7
|
+
str << @msgid2comment[msgid]
|
8
|
+
if str[-1] != "\n"[0]
|
9
|
+
str << "\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
id = msgid.gsub(/"/, '\"').gsub(/\r/, '')
|
13
|
+
msgstr = @msgid2msgstr[msgid].gsub(/"/, '\"').gsub(/\r/, '')
|
14
|
+
|
15
|
+
# MONKEY PATCHING START
|
16
|
+
if id.include?("\004")
|
17
|
+
ids = id.split(/\004/)
|
18
|
+
context = ids[0]
|
19
|
+
id = ids[1]
|
20
|
+
str << "msgctxt " << __conv(context) << "\n"
|
21
|
+
end
|
22
|
+
# MONKEY PATCHING END
|
23
|
+
|
24
|
+
if id.include?("\000")
|
25
|
+
ids = id.split(/\000/)
|
26
|
+
str << "msgid " << __conv(ids[0]) << "\n"
|
27
|
+
ids[1..-1].each do |single_id|
|
28
|
+
str << "msgid_plural " << __conv(single_id) << "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
msgstr.split("\000").each_with_index do |m, n|
|
32
|
+
str << "msgstr[#{n}] " << __conv(m) << "\n"
|
33
|
+
end
|
34
|
+
else
|
35
|
+
str << "msgid " << __conv(id) << "\n"
|
36
|
+
str << "msgstr " << __conv(msgstr) << "\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
str << "\n"
|
40
|
+
str
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'gettext/tools/poparser'
|
2
|
+
require 'gettext/tools/rmsgmerge'
|
3
|
+
require 'gettext-one_sky/my_po_data'
|
4
|
+
|
5
|
+
module GetText
|
6
|
+
module OneSky
|
7
|
+
class MyPoParser < GetText::PoParser
|
8
|
+
|
9
|
+
# MONKEY PATCHING START
|
10
|
+
# override to include blank trsanslation messages
|
11
|
+
def on_message(msgid, msgstr)
|
12
|
+
@data[msgid] = msgstr
|
13
|
+
@data.set_comment(msgid, @comments.join("\n"))
|
14
|
+
|
15
|
+
@comments.clear
|
16
|
+
@msgctxt = ""
|
17
|
+
end
|
18
|
+
# MONKEY PATCHING END
|
19
|
+
|
20
|
+
def parse_po_file(path, lang_code=nil)
|
21
|
+
gettext_formatted_messages = self.parse_file(path, GetText::RMsgMerge::PoData.new, false)
|
22
|
+
|
23
|
+
page_name = File.basename(path).gsub(/.pot$/, '.po')
|
24
|
+
to_onesky_format(gettext_formatted_messages, page_name, lang_code)
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_onesky_format(pot_file_path, new_phrases)
|
28
|
+
original_phrases = self.parse_file(pot_file_path, GetText::OneSky::MyPoData.new, false)
|
29
|
+
|
30
|
+
original_phrases.each_msgid do |full_msg_id|
|
31
|
+
msg_str = original_phrases.msgstr(full_msg_id)
|
32
|
+
|
33
|
+
if full_msg_id.include? "\004"
|
34
|
+
msg_context, msg_id = full_msg_id.split(/\004/)
|
35
|
+
|
36
|
+
if new_phrases.has_key?(msg_id) && new_phrases[msg_id].has_key?(msg_context)
|
37
|
+
value = new_phrases[msg_id][msg_context]
|
38
|
+
elsif msg_id.include? "\000"
|
39
|
+
msg_singular, msg_plural = msg_id.split(/\000/)
|
40
|
+
value = new_phrases[msg_singular]["Singular"] + "\000" + new_phrases[msg_plural]["Plural"]
|
41
|
+
else
|
42
|
+
value = ""
|
43
|
+
end
|
44
|
+
elsif full_msg_id.include? "\000"
|
45
|
+
msg_singular, msg_plural = full_msg_id.split(/\000/)
|
46
|
+
value = new_phrases[msg_singular]["Singular"] + "\000" + new_phrases[msg_plural]["Plural"]
|
47
|
+
else
|
48
|
+
if new_phrases[full_msg_id].is_a?(Hash)
|
49
|
+
value = new_phrases[full_msg_id]["General"]
|
50
|
+
else
|
51
|
+
value = new_phrases[full_msg_id]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
original_phrases[full_msg_id] = value
|
56
|
+
original_phrases.set_comment(full_msg_id, "")
|
57
|
+
end
|
58
|
+
|
59
|
+
original_phrases
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_onesky_format(messages, file_name, lang_code=nil)
|
63
|
+
slices = []
|
64
|
+
lang_options = Hash.new
|
65
|
+
lang_options[:language] = lang_code if lang_code
|
66
|
+
|
67
|
+
messages.each_msgid do |full_msg_id|
|
68
|
+
msg_id = full_msg_id
|
69
|
+
msg_str = messages.msgstr(msg_id)
|
70
|
+
|
71
|
+
components = Hash.new
|
72
|
+
if msg_id.include? "\004"
|
73
|
+
msg_context, msg_id = msg_id.split(/\004/)
|
74
|
+
components[:context] = msg_context
|
75
|
+
end
|
76
|
+
|
77
|
+
if msg_id.include? "\000"
|
78
|
+
msg_singular, msg_plural = msg_id.split(/\000/)
|
79
|
+
trans_singular, trans_plural = msg_str.split(/\000/)
|
80
|
+
|
81
|
+
slices << {:context => "Singular", :string => msg_singular, :"string-key" => msg_singular, :page => file_name, :translation => trans_singular || ""}.merge(lang_options)
|
82
|
+
slices << {:context => "Plural", :string => msg_plural, :"string-key" => msg_plural, :page => file_name, :translation => trans_plural || ""}.merge(lang_options)
|
83
|
+
else
|
84
|
+
slices << components.merge(:string => msg_id, :"string-key" => msg_id, :translation => msg_str, :page => file_name).merge(lang_options)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
assign_general_context(slices)
|
89
|
+
|
90
|
+
slices
|
91
|
+
end
|
92
|
+
|
93
|
+
def assign_general_context(slices)
|
94
|
+
general_slices = slices.select{|slice| !slice.has_key?(:context)}
|
95
|
+
general_slices.each do |general_slice|
|
96
|
+
if slices.select{|slice| slice[:string] == general_slice[:string] && slice.has_key?(:context)}.any?
|
97
|
+
general_slice[:context] = "General"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
namespace :one_sky do
|
2
|
+
desc "Upload phrases (.pot files) for translation to OneSky."
|
3
|
+
task :upload_phrases => :environment do
|
4
|
+
client = GetText::OneSky::SimpleClient.new
|
5
|
+
|
6
|
+
client.load_phrases
|
7
|
+
client.upload_phrases
|
8
|
+
|
9
|
+
puts "Phrases in .pot file uploaded to OneSky. Please ask your translators to... well... get translating."
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Upload translated phrases (.po files) to OneSky."
|
13
|
+
task :upload_translated_phrases => :environment do
|
14
|
+
client = GetText::OneSky::SimpleClient.new
|
15
|
+
|
16
|
+
client.load_translations
|
17
|
+
client.upload_translations
|
18
|
+
|
19
|
+
puts "Translated phrases in .po files uploaded to OneSky."
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Download available translations from OneSky and save as .po_from_one_sky."
|
23
|
+
task :download_translations do
|
24
|
+
client = GetText::OneSky::SimpleClient.new
|
25
|
+
|
26
|
+
client.download_translations
|
27
|
+
client.save_translations
|
28
|
+
|
29
|
+
puts "Latest translations downloaded and saved to po/**/*.po_from_one_sky files."
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'gettext-one_sky/my_po_parser'
|
2
|
+
|
3
|
+
module GetText
|
4
|
+
module OneSky
|
5
|
+
|
6
|
+
=begin
|
7
|
+
This class is the bridge between the OneSky service and the gettext file storgage.
|
8
|
+
It takes the phrases defined in gettext's default locale and uploads them to OneSky for translation.
|
9
|
+
Then it downloads available translations and saves them as .po files.
|
10
|
+
|
11
|
+
A regular workflow would then look like:
|
12
|
+
initialize -> load_phrases -> upload_phrases -> download_translations
|
13
|
+
|
14
|
+
|
15
|
+
* Initilaize *
|
16
|
+
|
17
|
+
When you initialize a client inside a Rails project,
|
18
|
+
it will take the OneSky configuration variables supplied when you called rails generate one_sky:init.
|
19
|
+
|
20
|
+
When you use this client outside of Rails,
|
21
|
+
credentials are expected to come from environment variables: ONESKY_API_KEY, ONESKY_API_SECRET, ONESKY_PROJECT.
|
22
|
+
You can override these defaults by providing a hash of options:
|
23
|
+
{:api_key => ..., :api_secret => ..., :project => ...}
|
24
|
+
|
25
|
+
=end
|
26
|
+
class SimpleClient
|
27
|
+
attr_reader :phrases_nested, :phrases_flat, :translations_flat, :translations_from_onesky
|
28
|
+
# The base OneSky project. Gives you low-level access to the API gem.
|
29
|
+
attr_reader :project
|
30
|
+
|
31
|
+
def initialize(options = {})
|
32
|
+
options = default_options.merge!(options)
|
33
|
+
@project = ::OneSky::Project.new(options[:api_key], options[:api_secret], options[:project])
|
34
|
+
@one_sky_locale = @project.details["base_locale"]
|
35
|
+
@one_sky_languages = @project.languages
|
36
|
+
end
|
37
|
+
|
38
|
+
# Parse and load phrases from .pot file.
|
39
|
+
# If not a Rails project, manually supply the path where the .pot file located.
|
40
|
+
def load_phrases(path=nil)
|
41
|
+
@phrases_flat = []
|
42
|
+
|
43
|
+
Dir.glob("#{po_dir_path(path)}/**/*.pot").each do |file_path|
|
44
|
+
@phrases_flat += parse_phrase_file(file_path)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Upload phrases to Onesky server
|
49
|
+
def upload_phrases(path = nil)
|
50
|
+
load_phrases(path) unless @phrases_flat
|
51
|
+
|
52
|
+
@project.input_bulk(@phrases_flat, :page => @phrases_flat.first[:page])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Parse and load translated phrases from .po files
|
56
|
+
# If not a Rails project, manually supply the path where the .po file path located.
|
57
|
+
def load_translations(path=nil)
|
58
|
+
@translations_flat = []
|
59
|
+
|
60
|
+
Dir.glob("#{po_dir_path(path)}/**/*.po").each do |file_path|
|
61
|
+
lang_code = File.dirname(file_path).split("/").last
|
62
|
+
|
63
|
+
@translations_flat += parse_phrase_file(file_path, lang_code)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Upload translated phrases to Onesky server
|
68
|
+
def upload_translations(path=nil)
|
69
|
+
load_translations(path) unless @translations_flat
|
70
|
+
|
71
|
+
@translations_flat.each do |values|
|
72
|
+
@project.send(:post, "/string/translate", values)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Download all available translations from Onesky server
|
77
|
+
def download_translations
|
78
|
+
@translations_from_onesky = @project.output
|
79
|
+
end
|
80
|
+
|
81
|
+
# Download all available translations from Onesky server and save them as *.po files.
|
82
|
+
def save_translations(path=nil)
|
83
|
+
download_translations unless @translations_from_onesky
|
84
|
+
|
85
|
+
update_translation_files_from_onesky(po_dir_path(path), @translations_from_onesky)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def default_options
|
93
|
+
if defined? Rails
|
94
|
+
YAML.load_file([Rails.root.to_s, 'config', 'one_sky.yml'].join('/')).symbolize_keys
|
95
|
+
else
|
96
|
+
{:api_key => ENV["ONESKY_API_KEY"], :api_secret => ENV["ONESKY_API_SECRET"], :project => ENV["ONESKY_PROJECT"]}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def po_dir_path(path)
|
101
|
+
if defined? Rails
|
102
|
+
path ||= [Rails.root.to_s, "po"].join("/")
|
103
|
+
else
|
104
|
+
raise ArgumentError, "Please supply the po directory path where locale files are to be downloaded." unless path && File.directory?(path)
|
105
|
+
path = path.chop if path =~ /\/$/
|
106
|
+
end
|
107
|
+
|
108
|
+
path
|
109
|
+
end
|
110
|
+
|
111
|
+
def update_translation_files_from_onesky(po_dir_path, translations)
|
112
|
+
# Delete all existing one_sky translation files before downloading a new set.
|
113
|
+
File.delete(*Dir.glob("#{po_dir_path}/**/*.po_from_one_sky"))
|
114
|
+
|
115
|
+
# Process each locale and save to file
|
116
|
+
translations.each_pair do |text_domain, values|
|
117
|
+
file_name = text_domain.gsub(/\.po$/, '')
|
118
|
+
pot_file_path = [po_dir_path, file_name + ".pot"].join('/')
|
119
|
+
|
120
|
+
values.each_pair do |lang_code, translated_phrases|
|
121
|
+
language_dir = "#{po_dir_path}/#{lang_code}"
|
122
|
+
Dir.mkdir(language_dir) unless File.exists?(language_dir)
|
123
|
+
po_from_one_sky_file = "#{language_dir}/#{file_name}.po_from_one_sky"
|
124
|
+
|
125
|
+
save_locale(pot_file_path, po_from_one_sky_file, lang_code, translated_phrases)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def save_locale(pot_file_path, po_file_name, lang_code, new_phrases)
|
131
|
+
my_po_parser = GetText::OneSky::MyPoParser.new
|
132
|
+
updated_phrases = my_po_parser.from_onesky_format(pot_file_path, new_phrases)
|
133
|
+
updated_phrases.set_comment(:last, "# END")
|
134
|
+
|
135
|
+
lang = @one_sky_languages.find { |e| e["locale"] == lang_code }
|
136
|
+
|
137
|
+
File.open(po_file_name, 'w') do |f|
|
138
|
+
f.print onesky_header(lang)
|
139
|
+
f.print updated_phrases.generate_po
|
140
|
+
end
|
141
|
+
po_file_name
|
142
|
+
end
|
143
|
+
|
144
|
+
def onesky_header(lang)
|
145
|
+
"# PLEASE DO NOT EDIT THIS FILE.\n" +
|
146
|
+
"# This was downloaded from OneSky. Log in to your OneSky account to manage translations on their website.\n" +
|
147
|
+
"# Language code: #{lang['locale']}\n" +
|
148
|
+
"# Language name: #{lang['locale_name']}\n" +
|
149
|
+
"# Language English name: #{lang['eng_name']}\n" +
|
150
|
+
"#\n"
|
151
|
+
"#\n"
|
152
|
+
end
|
153
|
+
|
154
|
+
def parse_translated_file(path=nil)
|
155
|
+
if defined? Rails
|
156
|
+
path ||= File.join(RAILS_ROOT, '/po', "**/*.po")
|
157
|
+
else
|
158
|
+
raise ArgumentError, "Please supply the path where the .po file is located." unless path
|
159
|
+
path = path.chop if path =~ /\/$/
|
160
|
+
end
|
161
|
+
|
162
|
+
parser = GetText::OneSky::MyPoParser.new
|
163
|
+
parser.parse_po_file(path)
|
164
|
+
end
|
165
|
+
|
166
|
+
def parse_phrase_file(path=nil, lang_code=nil)
|
167
|
+
raise ArgumentError, "Please supply the path where the .pot file is located." unless path
|
168
|
+
|
169
|
+
parser = GetText::OneSky::MyPoParser.new
|
170
|
+
parser.parse_po_file(path, lang_code)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
describe "SimpleClient End 2 End workflow" do
|
4
|
+
include GetTextOneSkySpecHelpers
|
5
|
+
|
6
|
+
before do
|
7
|
+
delete_onesky_project
|
8
|
+
create_onesky_project
|
9
|
+
|
10
|
+
@client = create_simple_client_and_load
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#upload_phrases" do
|
14
|
+
it "" do
|
15
|
+
@client.upload_phrases
|
16
|
+
@client.upload_transalcations
|
17
|
+
|
18
|
+
po_dir_path = [File.dirname(__FILE__), 'po'].join('/')
|
19
|
+
pot_file_path = [File.dirname(__FILE__), "po", "simple_client.pot"].join('/')
|
20
|
+
|
21
|
+
@client.download_translations(po_dir_path, pot_file_path).should be_a_kind_of Array
|
22
|
+
Dir.glob("#{po_dir_path}/**/from_one_sky.po").size.should >= 1
|
23
|
+
|
24
|
+
@client.translations["Hello"].should == "Too"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
$:.unshift File.expand_path('..', __FILE__)
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
|
4
|
+
require 'gettext-one_sky'
|
5
|
+
|
6
|
+
module GetTextOneSkySpecHelpers
|
7
|
+
def create_simple_client
|
8
|
+
raise "Please set environment variables: ONESKY_API_KEY, ONESKY_API_SECRET and ONESKY_SPEC_PROJ (default: gettextoneskyspec) before running spec." unless [ENV["ONESKY_API_KEY"], ENV["ONESKY_API_SECRET"]].all?
|
9
|
+
GetText.locale = "en_US"
|
10
|
+
client = GetText::OneSky::SimpleClient.new(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_simple_project
|
14
|
+
OneSky::Project.new(options[:api_key], options[:api_secret], options[:project])
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_simple_client_and_load
|
18
|
+
client = create_simple_client
|
19
|
+
|
20
|
+
load_phrases(client)
|
21
|
+
|
22
|
+
client
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_onesky_project(project)
|
26
|
+
begin
|
27
|
+
project.send(:post, "/project/delete", {:project => test_project_code})
|
28
|
+
rescue RestClient::BadRequest
|
29
|
+
retry
|
30
|
+
rescue OneSky::ApiError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_onesky_project(project)
|
35
|
+
project.send(:post, "/project/add", {:project => test_project_code, :type => "ruby", :"base-language-code" => "en_US"})
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def load_phrases(client)
|
41
|
+
client.load_phrases(po_dir_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_translations(client)
|
45
|
+
client.load_translations(po_dir_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
def po_dir_path
|
49
|
+
[File.dirname(__FILE__), "po"].join("/")
|
50
|
+
end
|
51
|
+
|
52
|
+
# hopefully not accidentally delete other real translation project
|
53
|
+
def test_project_code
|
54
|
+
"ONESKY_TEST_#{ENV["ONESKY_SPEC_PROJ"]}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def options
|
58
|
+
{
|
59
|
+
:api_key => ENV["ONESKY_API_KEY"],
|
60
|
+
:api_secret => ENV["ONESKY_API_SECRET"],
|
61
|
+
:project => test_project_code || "gettextoneskyspec"
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
5
|
+
#
|
6
|
+
msgid ""
|
7
|
+
msgstr ""
|
8
|
+
"Project-Id-Version: sample_client 1.0.0\n"
|
9
|
+
"POT-Creation-Date: 2011-07-30 23:34+0800\n"
|
10
|
+
"PO-Revision-Date: 2011-07-30 22:48+0800\n"
|
11
|
+
"Last-Translator: \n"
|
12
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
13
|
+
"Language: \n"
|
14
|
+
"MIME-Version: 1.0\n"
|
15
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
16
|
+
"Content-Transfer-Encoding: 8bit\n"
|
17
|
+
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
18
|
+
|
19
|
+
#: general msg
|
20
|
+
msgid "Hello"
|
21
|
+
msgstr "Updated Hello Plain"
|
22
|
+
|
23
|
+
|
24
|
+
#: single and plural msg
|
25
|
+
msgid "Stock"
|
26
|
+
msgid_plural "Stocks"
|
27
|
+
msgstr[0] "Updated Singular Stock"
|
28
|
+
msgstr[1] "Updated Plural Stocks"
|
29
|
+
|
30
|
+
|
31
|
+
#: msg with same name as context-ed msg
|
32
|
+
msgid "Good to Enter"
|
33
|
+
msgstr "Updated Time to enter order"
|
34
|
+
|
35
|
+
|
36
|
+
#: msg with context
|
37
|
+
msgctxt "Long"
|
38
|
+
msgid "Good to Enter"
|
39
|
+
msgstr "Updated Expect it to raise. Time to enter order"
|
40
|
+
|
41
|
+
|
42
|
+
#: msg with context
|
43
|
+
msgctxt "Short"
|
44
|
+
msgid "Good to Enter"
|
45
|
+
msgstr "Updated Expect it to drop. Time to enter order"
|
46
|
+
|
47
|
+
|
48
|
+
#: app/views/demo/index.rhtml:5
|
49
|
+
msgctxt "Not Supporting multi level of context and plural"
|
50
|
+
msgid "Should upload this singular phrase without context"
|
51
|
+
msgid_plural "Should upload this plural phrase without context"
|
52
|
+
msgstr[0] "Updated CONTEXT AND SING"
|
53
|
+
msgstr[1] "Updated CONTEXT AND PLURAL"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
5
|
+
#
|
6
|
+
msgid ""
|
7
|
+
msgstr ""
|
8
|
+
"Project-Id-Version: sample_client 1.0.0\n"
|
9
|
+
"POT-Creation-Date: 2011-07-30 23:34+0800\n"
|
10
|
+
"PO-Revision-Date: 2011-07-30 22:48+0800\n"
|
11
|
+
"Last-Translator: \n"
|
12
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
13
|
+
"Language: \n"
|
14
|
+
"MIME-Version: 1.0\n"
|
15
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
16
|
+
"Content-Transfer-Encoding: 8bit\n"
|
17
|
+
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
18
|
+
|
19
|
+
#: general msg
|
20
|
+
msgid "Hello"
|
21
|
+
msgstr ""
|
22
|
+
|
23
|
+
|
24
|
+
#: single and plural msg
|
25
|
+
msgid "Stock"
|
26
|
+
msgid_plural "Stocks"
|
27
|
+
msgstr[0] ""
|
28
|
+
msgstr[1] ""
|
29
|
+
|
30
|
+
|
31
|
+
#: msg with same name as context-ed msg
|
32
|
+
msgid "Good to Enter"
|
33
|
+
msgstr ""
|
34
|
+
|
35
|
+
|
36
|
+
#: msg with context
|
37
|
+
msgctxt "Long"
|
38
|
+
msgid "Good to Enter"
|
39
|
+
msgstr ""
|
40
|
+
|
41
|
+
|
42
|
+
#: msg with context
|
43
|
+
msgctxt "Short"
|
44
|
+
msgid "Good to Enter"
|
45
|
+
msgstr ""
|
46
|
+
|
47
|
+
|
48
|
+
#: app/views/demo/index.rhtml:5
|
49
|
+
msgctxt "Not Supporting multi level of context and plural"
|
50
|
+
msgid "Should upload this singular phrase without context"
|
51
|
+
msgid_plural "Should upload this plural phrase without context"
|
52
|
+
msgstr[0] ""
|
53
|
+
msgstr[1] ""
|
54
|
+
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
describe "SimpleClient" do
|
4
|
+
it "raises an error when initialization values are nil." do
|
5
|
+
lambda { @client = GetText::OneSky::SimpleClient.new(:api_key => nil, :api_secret => nil, :project => nil) }.should raise_error ArgumentError
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "SimpleClient" do
|
10
|
+
include GetTextOneSkySpecHelpers
|
11
|
+
|
12
|
+
before(:all) do
|
13
|
+
@project = create_simple_project
|
14
|
+
delete_onesky_project(@project)
|
15
|
+
create_onesky_project(@project)
|
16
|
+
|
17
|
+
@pot_file_path = [File.dirname(__FILE__), "po"].join('/')
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
@client = create_simple_client_and_load
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "project with phrases inside .pot file" do
|
25
|
+
describe "#load_phrases" do
|
26
|
+
it "should load flattened phrases." do
|
27
|
+
expected = [{:"string-key"=>"Hello", :page=>"simple_client.po", :string=>"Hello", :translation=>""},
|
28
|
+
{:"string-key"=>"Stock", :page=>"simple_client.po", :string=>"Stock", :context=>"Singular", :translation=>""},
|
29
|
+
{:"string-key"=>"Stocks", :page=>"simple_client.po", :string=>"Stocks", :context=>"Plural", :translation=>""},
|
30
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"General", :translation=>""},
|
31
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"Long", :translation=>""},
|
32
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"Short", :translation=>""},
|
33
|
+
{:"string-key"=>"Should upload this singular phrase without context", :page=>"simple_client.po", :string=>"Should upload this singular phrase without context", :context=>"Singular", :translation=>""},
|
34
|
+
{:"string-key"=>"Should upload this plural phrase without context", :page=>"simple_client.po", :string=>"Should upload this plural phrase without context", :context=>"Plural", :translation=>""}]
|
35
|
+
|
36
|
+
@client.phrases_flat.should == expected
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "Translation output from Onesky" do
|
41
|
+
before do
|
42
|
+
@client.upload_phrases.should be_true
|
43
|
+
@client.download_translations
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#download_translations" do
|
47
|
+
it "transforms translation result from Onesky" do
|
48
|
+
expected = { "simple_client.po" =>
|
49
|
+
{"en_US"=>
|
50
|
+
{"Good to Enter"=>
|
51
|
+
{"General" => "Good to Enter", "Short"=>"Good to Enter", "Long"=>"Good to Enter"},
|
52
|
+
"Stock"=>
|
53
|
+
{"Singular"=>"Stock"},
|
54
|
+
"Should upload this singular phrase without context"=>
|
55
|
+
{"Singular"=>"Should upload this singular phrase without context"},
|
56
|
+
"Should upload this plural phrase without context"=>
|
57
|
+
{"Plural"=>"Should upload this plural phrase without context"},
|
58
|
+
"Hello"=>"Hello",
|
59
|
+
"Stocks"=>
|
60
|
+
{"Plural"=>"Stocks"}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
@client.translations_from_onesky.should == expected
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#save_translations" do
|
70
|
+
it "saves the translation into .po files of all available languages." do
|
71
|
+
@client.save_translations(@pot_file_path)
|
72
|
+
|
73
|
+
Dir.glob("#{po_dir_path}/**/simple_client.po_from_one_sky").size.should >= 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "with translated .po files" do
|
80
|
+
before do
|
81
|
+
load_translations(@client)
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#load_translations" do
|
85
|
+
it "should load flattened translations." do
|
86
|
+
expected =
|
87
|
+
[{:"string-key"=>"Hello", :page=>"simple_client.po", :string=>"Hello", :translation=>"Updated Hello Plain", :language => "en_US"},
|
88
|
+
{:"string-key"=>"Stock", :page=>"simple_client.po", :string=>"Stock", :context=>"Singular", :translation=>"Updated Singular Stock", :language => "en_US"},
|
89
|
+
{:"string-key"=>"Stocks", :page=>"simple_client.po", :string=>"Stocks", :context=>"Plural", :translation=>"Updated Plural Stocks", :language => "en_US"},
|
90
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"General", :translation=>"Updated Time to enter order", :language => "en_US"},
|
91
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"Long", :translation=>"Updated Expect it to raise. Time to enter order", :language => "en_US"},
|
92
|
+
{:"string-key"=>"Good to Enter", :page=>"simple_client.po", :string=>"Good to Enter", :context=>"Short", :translation=>"Updated Expect it to drop. Time to enter order", :language => "en_US"},
|
93
|
+
{:"string-key"=>"Should upload this singular phrase without context", :page=>"simple_client.po", :string=>"Should upload this singular phrase without context", :context=>"Singular", :translation=>"Updated CONTEXT AND SING", :language => "en_US"},
|
94
|
+
{:"string-key"=>"Should upload this plural phrase without context", :page=>"simple_client.po", :string=>"Should upload this plural phrase without context", :context=>"Plural", :translation=>"Updated CONTEXT AND PLURAL", :language => "en_US"}]
|
95
|
+
|
96
|
+
@client.translations_flat.should == expected
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "retrieving updated translation output from Onesky" do
|
101
|
+
before do
|
102
|
+
@client.upload_translations.should be_true
|
103
|
+
@client.download_translations
|
104
|
+
end
|
105
|
+
|
106
|
+
########
|
107
|
+
# this test case does not work, because the original translation is always the default values returned
|
108
|
+
########
|
109
|
+
|
110
|
+
# describe "#download_translations" do
|
111
|
+
# it "transforms updated translation result from Onesky" do
|
112
|
+
# expected = { "simple_client.po" =>
|
113
|
+
# {"en_US"=>
|
114
|
+
# {"Good to Enter"=>
|
115
|
+
# {"General" => "Updated Time to enter order", "Short"=>"Updated Expect it to drop. Time to enter order", "Long"=>"Updated Expect it to raise. Time to enter order"},
|
116
|
+
# "Stock"=>
|
117
|
+
# {"Singular"=>"Updated Singular Stock"},
|
118
|
+
# "Should upload this singular phrase without context"=>
|
119
|
+
# {"Singular"=>"Updated CONTEXT AND SING"},
|
120
|
+
# "Should upload this plural phrase without context"=>
|
121
|
+
# {"Plural"=>"Updated CONTEXT AND PLURAL"},
|
122
|
+
# "Hello"=>"Updated Hello Plain",
|
123
|
+
# "Stocks"=>
|
124
|
+
# {"Plural"=>"Updated Plural Stocks"}
|
125
|
+
# }
|
126
|
+
# }
|
127
|
+
# }
|
128
|
+
#
|
129
|
+
# @client.translations_from_onesky.should == expected
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# describe "#save_translations" do
|
134
|
+
# it "saves the updated translation into .po files of all available languages." do
|
135
|
+
# @client.save_translations(@pot_file_path)
|
136
|
+
#
|
137
|
+
# Dir.glob("#{po_dir_path}/**/simple_client.po_from_one_sky").size.should >= 1
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gettext-one_sky
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Eddie Lau
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-09 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: gettext
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 15
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 2.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: one_sky
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 27
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 0
|
49
|
+
- 2
|
50
|
+
version: 0.0.2
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: thor
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 47
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 14
|
65
|
+
- 4
|
66
|
+
version: 0.14.4
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 7
|
78
|
+
segments:
|
79
|
+
- 2
|
80
|
+
- 2
|
81
|
+
- 0
|
82
|
+
version: 2.2.0
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: bundler
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 23
|
94
|
+
segments:
|
95
|
+
- 1
|
96
|
+
- 0
|
97
|
+
- 0
|
98
|
+
version: 1.0.0
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
101
|
+
description: This is a backport of i18n-one_sky-ruby to support gettext. i18n is not included in Rails before Rails 2.2. This gem handles the downloading and uploading translation files (.po) to Onesky server by calling Onesky API.
|
102
|
+
email:
|
103
|
+
- tatonlto@gmail.com
|
104
|
+
executables: []
|
105
|
+
|
106
|
+
extensions: []
|
107
|
+
|
108
|
+
extra_rdoc_files: []
|
109
|
+
|
110
|
+
files:
|
111
|
+
- .gitignore
|
112
|
+
- CHANGELOG
|
113
|
+
- CREDITS
|
114
|
+
- Gemfile
|
115
|
+
- Gemfile.lock
|
116
|
+
- MIT-LICENSE
|
117
|
+
- README.rdoc
|
118
|
+
- Rakefile
|
119
|
+
- gettext-one_sky.gemspec
|
120
|
+
- lib/generators/one_sky/init/init_generator.rb
|
121
|
+
- lib/gettext-one_sky.rb
|
122
|
+
- lib/gettext-one_sky/my_po_data.rb
|
123
|
+
- lib/gettext-one_sky/my_po_parser.rb
|
124
|
+
- lib/gettext-one_sky/rails/railtie.rb
|
125
|
+
- lib/gettext-one_sky/rails/tasks/gettext-one_sky.rake
|
126
|
+
- lib/gettext-one_sky/simple_client.rb
|
127
|
+
- lib/gettext-one_sky/version.rb
|
128
|
+
- spec/end_to_end_spec.rb
|
129
|
+
- spec/helpers.rb
|
130
|
+
- spec/po/en_US/simple_client.po
|
131
|
+
- spec/po/simple_client.pot
|
132
|
+
- spec/simple_client_spec.rb
|
133
|
+
has_rdoc: true
|
134
|
+
homepage: http://rubygems.org/gems/gettext-one_sky
|
135
|
+
licenses: []
|
136
|
+
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
hash: 3
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
version: "0"
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
hash: 3
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
version: "0"
|
160
|
+
requirements: []
|
161
|
+
|
162
|
+
rubyforge_project: gettext-one_sky
|
163
|
+
rubygems_version: 1.5.3
|
164
|
+
signing_key:
|
165
|
+
specification_version: 3
|
166
|
+
summary: gettext extensions using OneSky -- the community-powered translation service.
|
167
|
+
test_files:
|
168
|
+
- spec/end_to_end_spec.rb
|
169
|
+
- spec/helpers.rb
|
170
|
+
- spec/po/en_US/simple_client.po
|
171
|
+
- spec/po/simple_client.pot
|
172
|
+
- spec/simple_client_spec.rb
|