gettext-one_sky 0.0.1
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/.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
|