transync 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/bin/transync +0 -0
- data/lib/transync.rb +16 -15
- data/lib/transync/gdoc_trans/gdoc_trans_reader.rb +14 -18
- data/lib/transync/gdoc_trans/gdoc_trans_writer.rb +19 -14
- data/lib/transync/sync/init.rb +8 -20
- data/lib/transync/sync/sync_util.rb +12 -13
- data/lib/transync/sync/translation_sync.rb +50 -0
- data/lib/transync/{gdoc_trans/gdoc_trans.rb → transync_config.rb} +18 -7
- data/lib/transync/version.rb +1 -1
- data/lib/transync/xliff_trans/xliff_trans_reader.rb +29 -45
- data/lib/transync/xliff_trans/xliff_trans_writer.rb +11 -16
- data/test/fixtures/test.de.xliff +4 -0
- data/test/fixtures/test.en.xliff +4 -0
- data/test/fixtures/validators.en.xliff +5 -1
- data/test/g2x_spec.rb +50 -0
- data/test/x2g_spec.rb +57 -0
- metadata +10 -8
- data/lib/transync/sync/gdoc_2_xliff_main.rb +0 -39
- data/lib/transync/sync/gdoc_to_xliff.rb +0 -50
- data/lib/transync/sync/xliff_2_gdoc_main.rb +0 -41
- data/lib/transync/sync/xliff_to_gdoc.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e731d0853faec16a75252dfc64f65ae783d6a69
|
4
|
+
data.tar.gz: c26ef0c56ef0652d1a6a7cc93472965053fdbb83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92476f9124ea09d46e7b98574a07df504f73d5aa0bca336b39ebb87249253b38aa9d75791c91f9771996424c70319834b7cf04c47c718afb40271acdfad7b1e3
|
7
|
+
data.tar.gz: 6c5a099fca0df65ecbbf957ba6918e1d76b7d3936a1ca33403ea56b05432f973aabdb8bc34d12bbfb2d8d66c2828d40cb39ea489de0a6d0786d27a72658ba38b
|
data/README.md
CHANGED
@@ -47,6 +47,8 @@ Updating GDoc from our xliff files. It won't delete any key, it will only add ne
|
|
47
47
|
|
48
48
|
Gem docs available at http://gimite.net/doc/google-drive-ruby
|
49
49
|
|
50
|
-
#
|
50
|
+
# TODO
|
51
51
|
|
52
|
-
|
52
|
+
- more tests, edge cases
|
53
|
+
- more OOP
|
54
|
+
- update for more than 2 languages
|
data/bin/transync
CHANGED
File without changes
|
data/lib/transync.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require_relative 'transync/sync/
|
2
|
-
require_relative 'transync/sync/gdoc_2_xliff_main'
|
1
|
+
require_relative 'transync/sync/translation_sync'
|
3
2
|
require_relative 'transync/sync/init'
|
4
3
|
require_relative 'transync/sync/sync_util'
|
5
4
|
|
@@ -7,16 +6,11 @@ module Transync
|
|
7
6
|
|
8
7
|
def self.run(mode)
|
9
8
|
FileUtils.mkdir('.transync_log') unless Dir.exist?('.transync_log')
|
10
|
-
path =
|
9
|
+
path = TransyncConfig::CONFIG['XLIFF_FILES_PATH']
|
11
10
|
|
12
|
-
if mode == 'x2g'
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
if mode == 'g2x'
|
18
|
-
g2x = Gdoc2XliffMain.new(path)
|
19
|
-
g2x.run
|
11
|
+
if mode == 'x2g' or mode == 'g2x'
|
12
|
+
sync = TranslationSync.new(path, mode)
|
13
|
+
sync.run(mode)
|
20
14
|
end
|
21
15
|
|
22
16
|
if mode == 'init'
|
@@ -25,15 +19,22 @@ module Transync
|
|
25
19
|
end
|
26
20
|
|
27
21
|
if mode == 'test'
|
28
|
-
|
29
|
-
SyncUtil::check_and_get_xliff_files(
|
22
|
+
TransyncConfig::CONFIG['FILES'].each do |file|
|
23
|
+
SyncUtil::check_and_get_xliff_files(TransyncConfig::CONFIG['LANGUAGES'], path, file)
|
30
24
|
end
|
31
25
|
end
|
32
26
|
|
33
27
|
if mode == 'update'
|
34
|
-
|
35
|
-
|
28
|
+
TransyncConfig::CONFIG['FILES'].each do |file|
|
29
|
+
valid, _, all_translations_for_language =
|
30
|
+
SyncUtil::check_and_get_xliff_files(TransyncConfig::CONFIG['LANGUAGES'], path, file)
|
31
|
+
|
32
|
+
unless valid
|
33
|
+
xliff_trans_writer = XliffTransWriter.new(path, file)
|
34
|
+
xliff_trans_writer.write(all_translations_for_language)
|
35
|
+
end
|
36
36
|
end
|
37
|
+
p 'All xliff files should now have all the keys!'
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -1,27 +1,23 @@
|
|
1
|
-
|
2
|
-
require_relative 'gdoc_trans'
|
1
|
+
require_relative '../transync_config'
|
3
2
|
|
4
3
|
class GdocTransReader
|
5
|
-
|
4
|
+
attr_reader :worksheet
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# select the right tab from worksheet
|
12
|
-
self.worksheet = worksheet_tabs.detect{ |w| w.title == tab }
|
13
|
-
abort("#{tab} tab is not defined in GDoc") if self.worksheet.nil?
|
6
|
+
# file represents tab in spreadsheet
|
7
|
+
def initialize(file)
|
8
|
+
@worksheet = TransyncConfig::WORKSHEETS.detect{ |w| w.title == file }
|
9
|
+
abort("#{file} tab is not defined in GDoc") if @worksheet.nil?
|
14
10
|
end
|
15
11
|
|
16
|
-
def
|
17
|
-
trans_hash = {
|
18
|
-
|
19
|
-
|
20
|
-
language_column = GdocTrans::WORKSHEET_COLUMNS[language.to_sym]
|
12
|
+
def translations(language)
|
13
|
+
trans_hash = { file: @worksheet.title, language: language, translations: {} }
|
14
|
+
key_column = TransyncConfig::WORKSHEET_COLUMNS[:key]
|
15
|
+
language_column = TransyncConfig::WORKSHEET_COLUMNS[language.to_sym]
|
21
16
|
|
22
|
-
(
|
23
|
-
|
24
|
-
|
17
|
+
(TransyncConfig::START_ROW..@worksheet.num_rows).to_a.each do |row|
|
18
|
+
key = @worksheet[row, key_column]
|
19
|
+
value = @worksheet[row, language_column]
|
20
|
+
trans_hash[:translations][key] = value
|
25
21
|
end
|
26
22
|
|
27
23
|
trans_hash
|
@@ -1,28 +1,33 @@
|
|
1
1
|
require 'google_drive'
|
2
|
-
require_relative 'gdoc_trans'
|
3
2
|
|
4
3
|
class GdocTransWriter
|
5
|
-
attr_accessor :worksheet
|
6
4
|
|
7
5
|
def initialize(worksheet)
|
8
6
|
@worksheet = worksheet
|
9
7
|
end
|
10
8
|
|
11
|
-
def write(
|
12
|
-
|
13
|
-
|
9
|
+
def write(trans_hash)
|
10
|
+
language = trans_hash[:language]
|
11
|
+
lang_column = get_language_column_index(language)
|
12
|
+
abort("Language (#{language}) not found in worksheet (#{@worksheet.title})!") if lang_column == 0
|
13
|
+
|
14
|
+
row = 2
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@worksheet[new_row, col] = ''
|
21
|
-
@worksheet[new_row + 1, col] = cell
|
22
|
-
end
|
16
|
+
trans_hash[:translations].keys.each do |trans_key|
|
17
|
+
trans_value = trans_hash[:translations][trans_key]
|
18
|
+
@worksheet[row, 1] = trans_key
|
19
|
+
@worksheet[row, lang_column] = trans_value
|
20
|
+
row += 1
|
23
21
|
end
|
24
22
|
|
25
|
-
@worksheet
|
23
|
+
@worksheet.save
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_language_column_index(language)
|
27
|
+
(2..@worksheet.num_cols).each do |column|
|
28
|
+
return column if @worksheet[1, column].downcase == language.downcase
|
29
|
+
end
|
30
|
+
0
|
26
31
|
end
|
27
32
|
|
28
33
|
end
|
data/lib/transync/sync/init.rb
CHANGED
@@ -1,26 +1,15 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require_relative '../gdoc_trans/gdoc_trans_writer'
|
3
|
-
require_relative 'xliff_to_gdoc'
|
4
|
-
|
5
1
|
class Init
|
6
|
-
attr_reader :path, :config
|
7
2
|
|
8
3
|
def initialize(path)
|
9
|
-
@path
|
10
|
-
@config =
|
11
|
-
@gdoc_access = @config['GDOC']
|
4
|
+
@path = path
|
5
|
+
@config = TransyncConfig::CONFIG
|
12
6
|
end
|
13
7
|
|
14
8
|
def run
|
15
|
-
# first we want to add all the files to spreadsheet as worksheets (tabs)
|
16
|
-
# add_worksheet(title, max_rows = 100, max_cols = 20)
|
17
|
-
session = GoogleDrive.login(@gdoc_access['email'], @gdoc_access['password'])
|
18
|
-
spreadsheet = session.spreadsheet_by_key(@gdoc_access['key'])
|
19
|
-
|
20
9
|
@config['FILES'].each do |file|
|
21
|
-
worksheet =
|
10
|
+
worksheet = TransyncConfig::WORKSHEETS.detect{ |s| s.title == file }
|
22
11
|
if worksheet.nil?
|
23
|
-
worksheet =
|
12
|
+
worksheet = TransyncConfig::SPREADSHEET.add_worksheet(file)
|
24
13
|
p "Adding #{file} worksheet to spreadsheet with first row (key and languages)"
|
25
14
|
end
|
26
15
|
|
@@ -31,11 +20,10 @@ class Init
|
|
31
20
|
worksheet.save
|
32
21
|
end
|
33
22
|
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
x2g.run
|
23
|
+
# re-init spreadsheet after new worksheets were created
|
24
|
+
TransyncConfig.init_spreadsheet
|
25
|
+
sync = TranslationSync.new(@path, 'x2g')
|
26
|
+
sync.run('x2g')
|
39
27
|
end
|
40
28
|
|
41
29
|
end
|
@@ -3,23 +3,22 @@ require_relative '../xliff_trans/xliff_trans_reader'
|
|
3
3
|
|
4
4
|
module SyncUtil
|
5
5
|
|
6
|
-
def self.check_and_get_xliff_files(languages, path, file
|
6
|
+
def self.check_and_get_xliff_files(languages, path, file)
|
7
|
+
valid = true
|
7
8
|
xliff_translations = []
|
8
|
-
|
9
|
+
all_translations_for_language = {}
|
9
10
|
|
10
11
|
languages.each do |language|
|
11
|
-
xliff_reader = XliffTransReader.new(path, file,
|
12
|
-
if xliff_reader.valid?
|
13
|
-
xliff_translations << xliff_reader.
|
12
|
+
xliff_reader = XliffTransReader.new(path, file, languages)
|
13
|
+
if xliff_reader.valid?
|
14
|
+
xliff_translations << xliff_reader.translations(language)
|
14
15
|
else
|
15
|
-
|
16
|
-
|
16
|
+
valid = false
|
17
|
+
all_translations_for_language = xliff_reader.all_translations_for_language
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
xliff_translations
|
21
|
+
return valid, xliff_translations, all_translations_for_language
|
23
22
|
end
|
24
23
|
|
25
24
|
def self.info_clean(file, language, message)
|
@@ -27,8 +26,9 @@ module SyncUtil
|
|
27
26
|
SyncUtil.log_and_puts(msg)
|
28
27
|
end
|
29
28
|
|
30
|
-
def self.info_diff(file, language, operation,
|
31
|
-
msg = "#{file} (#{language}) - #{operation}: '#{
|
29
|
+
def self.info_diff(file, language, operation, trans_key, trans_value)
|
30
|
+
msg = "#{file} (#{language}) - #{operation}: '#{trans_key}'"
|
31
|
+
msg += " to '#{trans_value}'" unless trans_value.nil?
|
32
32
|
SyncUtil.log_and_puts(msg)
|
33
33
|
end
|
34
34
|
|
@@ -38,7 +38,6 @@ module SyncUtil
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.create_logger(direction)
|
41
|
-
# gdoc2xliff or xliff2gdoc
|
42
41
|
@logger = Logger.new(".transync_log/#{direction}.log", 'monthly')
|
43
42
|
end
|
44
43
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative '../gdoc_trans/gdoc_trans_reader'
|
2
|
+
require_relative '../gdoc_trans/gdoc_trans_writer'
|
3
|
+
require_relative '../xliff_trans/xliff_trans_writer'
|
4
|
+
|
5
|
+
class TranslationSync
|
6
|
+
|
7
|
+
def initialize(path, direction, file = nil)
|
8
|
+
@path = path
|
9
|
+
@file = file
|
10
|
+
@config = TransyncConfig::CONFIG
|
11
|
+
SyncUtil.create_logger(direction)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(direction)
|
15
|
+
@config['FILES'].each do |file|
|
16
|
+
valid, _ = SyncUtil::check_and_get_xliff_files(@config['LANGUAGES'], @path, file)
|
17
|
+
abort('Fix your Xliff translations first!') unless valid
|
18
|
+
|
19
|
+
@config['LANGUAGES'].each do |language|
|
20
|
+
trans_sync = TranslationSync.new(@path, direction, file)
|
21
|
+
trans_hash = trans_sync.sync(language, direction)
|
22
|
+
|
23
|
+
if direction == 'x2g'
|
24
|
+
gdoc_trans_reader = GdocTransReader.new(file)
|
25
|
+
gdoc_trans_writer = GdocTransWriter.new(gdoc_trans_reader.worksheet)
|
26
|
+
gdoc_trans_writer.write(trans_hash)
|
27
|
+
else
|
28
|
+
xliff_trans_writer = XliffTransWriter.new(@path, file)
|
29
|
+
xliff_trans_writer.write(trans_hash)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def sync(language, direction)
|
36
|
+
gdoc_trans_reader = GdocTransReader.new(@file)
|
37
|
+
xliff_trans_reader = XliffTransReader.new(@path, @file, nil) # we dont need languages for translations method
|
38
|
+
|
39
|
+
g_trans_hash = gdoc_trans_reader.translations(language)
|
40
|
+
x_trans_hash = xliff_trans_reader.translations(language)
|
41
|
+
|
42
|
+
# We need to merge on translations hash, not whole hash since it will only merge first level
|
43
|
+
x2g_merged_translations = g_trans_hash[:translations].merge(x_trans_hash[:translations])
|
44
|
+
g2x_merged_translations = x_trans_hash[:translations].merge(g_trans_hash[:translations])
|
45
|
+
|
46
|
+
merged_translations = direction == 'x2g' ? x2g_merged_translations : g2x_merged_translations
|
47
|
+
{file: @file, language: language, translations: merged_translations}
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -1,11 +1,26 @@
|
|
1
|
-
|
1
|
+
require 'yaml'
|
2
|
+
require 'google_drive'
|
3
|
+
|
4
|
+
module TransyncConfig
|
5
|
+
# Result of WORKSHEET_COLUMNS should be something like this
|
6
|
+
# depends on LANGUAGES set in settings yaml file
|
7
|
+
# WORKSHEET_COLUMNS = { key: 1, en: 2, de: 3 }
|
2
8
|
WORKSHEET_COLUMNS = { key: 1 }
|
3
9
|
START_ROW = 2
|
4
10
|
|
11
|
+
def self.init_spreadsheet
|
12
|
+
session = GoogleDrive.login(CONFIG['GDOC']['email'], CONFIG['GDOC']['password'])
|
13
|
+
spreadsheet = session.spreadsheet_by_key(CONFIG['GDOC']['key'])
|
14
|
+
worksheets = spreadsheet.worksheets
|
15
|
+
|
16
|
+
return spreadsheet, worksheets
|
17
|
+
end
|
18
|
+
|
5
19
|
begin
|
6
20
|
CONFIG = YAML.load(File.open('transync.yml'))
|
7
|
-
|
8
|
-
|
21
|
+
SPREADSHEET, WORKSHEETS = TransyncConfig.init_spreadsheet
|
22
|
+
rescue => e
|
23
|
+
p e.message
|
9
24
|
exit(1)
|
10
25
|
end
|
11
26
|
|
@@ -15,8 +30,4 @@ module GdocTrans
|
|
15
30
|
value = index + 2
|
16
31
|
WORKSHEET_COLUMNS[key.to_sym] = value
|
17
32
|
end
|
18
|
-
|
19
|
-
# Result of WORKSHEET_COLUMNS should be something like this
|
20
|
-
# depends on LANGUAGES set in settings yaml file
|
21
|
-
# WORKSHEET_COLUMNS = { key: 1, en: 2, de: 3 }
|
22
33
|
end
|
data/lib/transync/version.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
|
3
3
|
class XliffTransReader
|
4
|
-
attr_accessor :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.
|
4
|
+
attr_accessor :path,
|
5
|
+
:file,
|
6
|
+
:languages,
|
7
|
+
:all_translations_for_language
|
8
|
+
|
9
|
+
def initialize(path, file, languages)
|
10
|
+
self.path = path
|
11
|
+
self.file = file
|
12
|
+
self.languages = languages
|
13
|
+
self.all_translations_for_language = {file: file, language: nil, translations: {}}
|
11
14
|
end
|
12
15
|
|
13
|
-
def
|
14
|
-
data = {
|
15
|
-
language: language,
|
16
|
-
translations: []
|
17
|
-
}
|
16
|
+
def translations(language)
|
17
|
+
data = { file: file, language: language, translations: {} }
|
18
18
|
|
19
|
-
open_file do |doc|
|
20
|
-
# hacky hack, xliff is dirty as hell
|
19
|
+
open_file(language) do |doc|
|
21
20
|
doc.remove_namespaces!
|
22
21
|
doc.xpath('//trans-unit').each do |node|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
}
|
22
|
+
key = node.xpath('source').text
|
23
|
+
value = node.xpath('target').text
|
24
|
+
data[:translations][key] = value
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
@@ -31,49 +29,35 @@ class XliffTransReader
|
|
31
29
|
end
|
32
30
|
|
33
31
|
# will go through each and find if any xliff is missing keys for translations
|
34
|
-
def valid?
|
32
|
+
def valid?
|
35
33
|
missing = 0
|
36
|
-
missing_translation_text =
|
37
|
-
all_translations_for_language = {language: nil, translations: []}
|
34
|
+
missing_translation_text = TransyncConfig::CONFIG['MISSING_TRANSLATION_TEXT'] || '#MISSING-TRANS#'
|
38
35
|
|
39
|
-
self.
|
36
|
+
self.translations(self.languages.first)[:translations].keys.each do |x_trans_key|
|
40
37
|
self.languages.each do |key_lang|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
xliff_lang = xliff_reader.get_translations[:translations]
|
45
|
-
xliff_lang_value = xliff_lang.detect{ |xt| xt[:key] == x_trans[:key] }
|
38
|
+
xliff_reader = XliffTransReader.new(self.path, self.file, self.languages)
|
39
|
+
xliff_lang = xliff_reader.translations(key_lang)[:translations]
|
40
|
+
xliff_lang_value = xliff_lang[x_trans_key]
|
46
41
|
|
47
42
|
all_translations_for_language[:language] = key_lang
|
48
43
|
|
49
44
|
if xliff_lang_value.nil?
|
50
|
-
p "#{file}.#{key_lang} is missing translation for key '#{
|
51
|
-
|
52
|
-
|
53
|
-
p "#{missing + 1}. #{file}.#{key_lang} was missing translation for key '#{x_trans[:key]}'."
|
54
|
-
all_translations_for_language[:translations] << {
|
55
|
-
key: x_trans[:key],
|
56
|
-
value: "#{missing_translation_text} - #{x_trans[:key]}"
|
57
|
-
}
|
45
|
+
p "#{file}.#{key_lang} is missing translation for key '#{x_trans_key}'"
|
46
|
+
all_translations_for_language[:translations][x_trans_key] = "#{missing_translation_text} - #{x_trans_key}"
|
58
47
|
missing += 1
|
59
48
|
else
|
60
|
-
all_translations_for_language[:translations]
|
49
|
+
all_translations_for_language[:translations][x_trans_key] = xliff_lang_value
|
61
50
|
end
|
62
51
|
end
|
63
52
|
end
|
64
53
|
|
65
|
-
if missing > 0 and create
|
66
|
-
xliff_trans_writer = XliffTransWriter.new(dir, file, all_translations_for_language)
|
67
|
-
xliff_trans_writer.save
|
68
|
-
end
|
69
|
-
|
70
54
|
missing == 0
|
71
55
|
end
|
72
56
|
|
73
57
|
# Reading from source tags in xliff
|
74
|
-
def open_file
|
58
|
+
def open_file(language)
|
75
59
|
begin
|
76
|
-
xml_file = File.open(file_path)
|
60
|
+
xml_file = File.open(file_path(language))
|
77
61
|
doc = Nokogiri::XML(xml_file)
|
78
62
|
yield doc
|
79
63
|
rescue Errno::ENOENT => e
|
@@ -83,8 +67,8 @@ class XliffTransReader
|
|
83
67
|
|
84
68
|
private
|
85
69
|
|
86
|
-
def file_path
|
87
|
-
"#{
|
70
|
+
def file_path(language)
|
71
|
+
"#{path}/#{file}.#{language}.xliff"
|
88
72
|
end
|
89
73
|
|
90
74
|
end
|
@@ -1,20 +1,15 @@
|
|
1
1
|
require 'builder'
|
2
2
|
|
3
3
|
class XliffTransWriter
|
4
|
-
attr_accessor :data,
|
5
|
-
:path,
|
6
|
-
:file,
|
7
|
-
:language
|
8
4
|
|
9
|
-
def initialize(path, file
|
5
|
+
def initialize(path, file)
|
10
6
|
@path = path
|
11
7
|
@file = file
|
12
|
-
@language = data[:language]
|
13
|
-
@data = data
|
14
8
|
end
|
15
9
|
|
16
|
-
def
|
17
|
-
|
10
|
+
def write(trans_hash)
|
11
|
+
language = trans_hash[:language]
|
12
|
+
translations = trans_hash[:translations]
|
18
13
|
|
19
14
|
xml = Builder::XmlMarkup.new( :indent => 4 )
|
20
15
|
xml.instruct! :xml, :encoding => 'UTF-8'
|
@@ -22,10 +17,10 @@ class XliffTransWriter
|
|
22
17
|
xliff.file :'source-language' => language, :datatype => 'plaintext', :original => 'file.ext' do |file|
|
23
18
|
file.body do |body|
|
24
19
|
|
25
|
-
translations.each do |
|
26
|
-
body.tag! 'trans-unit', :id =>
|
27
|
-
trans_unit.source
|
28
|
-
trans_unit.target
|
20
|
+
translations.keys.each do |trans_key|
|
21
|
+
body.tag! 'trans-unit', :id => trans_key do |trans_unit|
|
22
|
+
trans_unit.source trans_key
|
23
|
+
trans_unit.target translations[trans_key]
|
29
24
|
end
|
30
25
|
end
|
31
26
|
|
@@ -33,13 +28,13 @@ class XliffTransWriter
|
|
33
28
|
end
|
34
29
|
end
|
35
30
|
|
36
|
-
File.open(file_path, 'w') { |file| file.write(xml.target!) }
|
31
|
+
File.open(file_path(language), 'w') { |file| file.write(xml.target!) }
|
37
32
|
end
|
38
33
|
|
39
34
|
private
|
40
35
|
|
41
|
-
def file_path
|
42
|
-
"#{path}/#{file}.#{language}.xliff"
|
36
|
+
def file_path(language)
|
37
|
+
"#{@path}/#{@file}.#{language}.xliff"
|
43
38
|
end
|
44
39
|
|
45
40
|
end
|
data/test/fixtures/test.de.xliff
CHANGED
data/test/fixtures/test.en.xliff
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
3
|
-
<file source-language="
|
3
|
+
<file source-language="en" datatype="plaintext" original="file.ext">
|
4
4
|
<body>
|
5
5
|
<trans-unit id="title">
|
6
6
|
<source>title</source>
|
7
7
|
<target>Titel</target>
|
8
8
|
</trans-unit>
|
9
|
+
<trans-unit id="end_test_2">
|
10
|
+
<source>end_test_2</source>
|
11
|
+
<target>End test 2</target>
|
12
|
+
</trans-unit>
|
9
13
|
<trans-unit id="round">
|
10
14
|
<source>round</source>
|
11
15
|
<target>Rund</target>
|
data/test/g2x_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require_relative '../lib/transync/transync_config'
|
5
|
+
require_relative '../lib/transync/gdoc_trans/gdoc_trans_reader'
|
6
|
+
require_relative '../lib/transync/sync/sync_util'
|
7
|
+
require_relative '../lib/transync/sync/translation_sync'
|
8
|
+
|
9
|
+
# Expects this data in test worksheet
|
10
|
+
# Key EN DE
|
11
|
+
# title Title Titel
|
12
|
+
# round Round Rund
|
13
|
+
# end_test meh xxx
|
14
|
+
describe 'g2x' do
|
15
|
+
before do
|
16
|
+
@file = 'test' # file or worksheet title aka spreadsheet tab
|
17
|
+
@path = 'test/fixtures'
|
18
|
+
@language = 'en'
|
19
|
+
SyncUtil.create_logger('g2x_test')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'google doc translation reader should build correct trans hash' do
|
23
|
+
gdoc_trans_reader = GdocTransReader.new(@file)
|
24
|
+
trans_hash = gdoc_trans_reader.translations(@language)
|
25
|
+
trans_hash[:file].must_equal @file
|
26
|
+
trans_hash[:language].must_equal @language
|
27
|
+
trans_hash[:translations].keys.size.must_equal 3
|
28
|
+
|
29
|
+
trans_hash[:translations]['title'].must_equal 'Title'
|
30
|
+
trans_hash[:translations]['round'].must_equal 'Round'
|
31
|
+
trans_hash[:translations]['end_test'].must_equal 'meh'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'g2x sync should build new hash before writing it to xliff' do
|
35
|
+
_, xliff_translations = SyncUtil::check_and_get_xliff_files(%w(en), @path, @file)
|
36
|
+
xliff_translations[0][:file].must_equal @file
|
37
|
+
xliff_translations[0][:language].must_equal @language
|
38
|
+
xliff_translations[0][:translations].keys.size.must_equal 4
|
39
|
+
|
40
|
+
trans_sync = TranslationSync.new(@path, 'g2x', @file)
|
41
|
+
new_xliff_hash = trans_sync.sync(@language, 'g2x')
|
42
|
+
|
43
|
+
new_xliff_hash[:file].must_equal @file
|
44
|
+
new_xliff_hash[:language].must_equal @language
|
45
|
+
new_xliff_hash[:translations].size.must_equal 4
|
46
|
+
|
47
|
+
new_xliff_hash[:translations]['end_test'].must_equal 'meh'
|
48
|
+
new_xliff_hash[:translations]['end_test_2'].must_equal 'End test 2'
|
49
|
+
end
|
50
|
+
end
|
data/test/x2g_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require_relative '../lib/transync/transync_config'
|
5
|
+
require_relative '../lib/transync/gdoc_trans/gdoc_trans_reader'
|
6
|
+
require_relative '../lib/transync/gdoc_trans/gdoc_trans_writer'
|
7
|
+
require_relative '../lib/transync/sync/sync_util'
|
8
|
+
require_relative '../lib/transync/sync/translation_sync'
|
9
|
+
require_relative '../lib/transync/xliff_trans/xliff_trans_reader'
|
10
|
+
|
11
|
+
describe 'x2g' do
|
12
|
+
before do
|
13
|
+
@file = 'test'
|
14
|
+
@path = 'test/fixtures'
|
15
|
+
@language = 'en'
|
16
|
+
@languages = %w(en de)
|
17
|
+
SyncUtil.create_logger('x2g_test')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'test if xliff files are valid' do
|
21
|
+
xliff_trans_reader = XliffTransReader.new(@path, 'test', @languages)
|
22
|
+
valid = xliff_trans_reader.valid?
|
23
|
+
valid.must_equal true
|
24
|
+
|
25
|
+
xliff_trans_reader = XliffTransReader.new(@path, 'validators', @languages)
|
26
|
+
valid = xliff_trans_reader.valid?
|
27
|
+
valid.must_equal false, 'validators translations should not be valid, because we do not have all keys in german file.'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'test if all keys in all language files are presented' do
|
31
|
+
valid, _, _ = SyncUtil::check_and_get_xliff_files(TransyncConfig::CONFIG['LANGUAGES'], @path, 'test')
|
32
|
+
valid.must_equal true, 'test file should have all keys in both languages'
|
33
|
+
|
34
|
+
valid, _, all_trans = SyncUtil::check_and_get_xliff_files(TransyncConfig::CONFIG['LANGUAGES'], @path, 'validators')
|
35
|
+
valid.must_equal false, 'validators.de file is should have one key less then validators.en xliff file'
|
36
|
+
all_trans[:translations].size.must_equal 4
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'x2g sync should build correct new hash before writing it back to google doc' do
|
40
|
+
trans_sync = TranslationSync.new(@path, 'x2g', @file)
|
41
|
+
trans_hash = trans_sync.sync(@language, 'x2g')
|
42
|
+
|
43
|
+
trans_hash[:file].must_equal @file
|
44
|
+
trans_hash[:language].must_equal @language
|
45
|
+
trans_hash[:translations].keys.size.must_equal 4
|
46
|
+
|
47
|
+
trans_hash[:translations]['title'].must_equal 'Title'
|
48
|
+
trans_hash[:translations]['round'].must_equal 'Round'
|
49
|
+
trans_hash[:translations]['end_test'].must_equal 'End test'
|
50
|
+
trans_hash[:translations]['end_test_2'].must_equal 'End test 2'
|
51
|
+
|
52
|
+
gdoc_trans_reader = GdocTransReader.new(@file)
|
53
|
+
gdoc_trans_writer = GdocTransWriter.new(gdoc_trans_reader.worksheet)
|
54
|
+
gdoc_trans_writer.get_language_column_index('en').must_equal 2
|
55
|
+
gdoc_trans_writer.get_language_column_index('DE').must_equal 3
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zigomir
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google_drive
|
@@ -82,15 +82,12 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- bin/transync
|
84
84
|
- lib/transync.rb
|
85
|
-
- lib/transync/gdoc_trans/gdoc_trans.rb
|
86
85
|
- lib/transync/gdoc_trans/gdoc_trans_reader.rb
|
87
86
|
- lib/transync/gdoc_trans/gdoc_trans_writer.rb
|
88
|
-
- lib/transync/sync/gdoc_2_xliff_main.rb
|
89
|
-
- lib/transync/sync/gdoc_to_xliff.rb
|
90
87
|
- lib/transync/sync/init.rb
|
91
88
|
- lib/transync/sync/sync_util.rb
|
92
|
-
- lib/transync/sync/
|
93
|
-
- lib/transync/
|
89
|
+
- lib/transync/sync/translation_sync.rb
|
90
|
+
- lib/transync/transync_config.rb
|
94
91
|
- lib/transync/version.rb
|
95
92
|
- lib/transync/xliff_trans/xliff_trans_reader.rb
|
96
93
|
- lib/transync/xliff_trans/xliff_trans_writer.rb
|
@@ -98,6 +95,8 @@ files:
|
|
98
95
|
- test/fixtures/test.en.xliff
|
99
96
|
- test/fixtures/validators.de.xliff
|
100
97
|
- test/fixtures/validators.en.xliff
|
98
|
+
- test/g2x_spec.rb
|
99
|
+
- test/x2g_spec.rb
|
101
100
|
- transync.SAMPLE.yml
|
102
101
|
- transync.gemspec
|
103
102
|
homepage: ''
|
@@ -120,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
119
|
version: '0'
|
121
120
|
requirements: []
|
122
121
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.0.
|
122
|
+
rubygems_version: 2.0.3
|
124
123
|
signing_key:
|
125
124
|
specification_version: 4
|
126
125
|
summary: Synchronize XLIFF translations with Google Drive document
|
@@ -129,3 +128,6 @@ test_files:
|
|
129
128
|
- test/fixtures/test.en.xliff
|
130
129
|
- test/fixtures/validators.de.xliff
|
131
130
|
- test/fixtures/validators.en.xliff
|
131
|
+
- test/g2x_spec.rb
|
132
|
+
- test/x2g_spec.rb
|
133
|
+
has_rdoc:
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require_relative '../gdoc_trans/gdoc_trans_reader'
|
3
|
-
require_relative '../xliff_trans/xliff_trans_writer'
|
4
|
-
require_relative 'gdoc_to_xliff'
|
5
|
-
require_relative 'sync_util'
|
6
|
-
|
7
|
-
class Gdoc2XliffMain
|
8
|
-
attr_reader :path, :config
|
9
|
-
|
10
|
-
def initialize(path)
|
11
|
-
@path = path
|
12
|
-
@config = GdocTrans::CONFIG
|
13
|
-
SyncUtil.create_logger('gdoc2xliff')
|
14
|
-
end
|
15
|
-
|
16
|
-
def run
|
17
|
-
@config['FILES'].each do |file|
|
18
|
-
xliff_translations = SyncUtil::check_and_get_xliff_files(@config['LANGUAGES'], path, file)
|
19
|
-
gdoc_trans_reader = GdocTransReader.new(@config['GDOC'], file)
|
20
|
-
|
21
|
-
@config['LANGUAGES'].each do |language|
|
22
|
-
options = {
|
23
|
-
xliff_translations: xliff_translations,
|
24
|
-
gdoc_trans_reader: gdoc_trans_reader,
|
25
|
-
language: language
|
26
|
-
}
|
27
|
-
|
28
|
-
gdoc_to_xliff = GdocToXliff.new(options)
|
29
|
-
dirty, new_xliff_hash = gdoc_to_xliff.sync
|
30
|
-
|
31
|
-
xliff_trans_writer = XliffTransWriter.new(path, file, new_xliff_hash)
|
32
|
-
xliff_trans_writer.save if dirty
|
33
|
-
|
34
|
-
SyncUtil.info_clean(file, language, 'was clean. Already has same keys and values inside Xliff') unless dirty
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require_relative 'sync_util'
|
2
|
-
|
3
|
-
class GdocToXliff
|
4
|
-
attr_accessor :xliff_translations,
|
5
|
-
:gdoc_trans_reader,
|
6
|
-
:language
|
7
|
-
|
8
|
-
def initialize(options = {})
|
9
|
-
self.xliff_translations = options[:xliff_translations]
|
10
|
-
self.gdoc_trans_reader = options[:gdoc_trans_reader]
|
11
|
-
self.language = options[:language]
|
12
|
-
end
|
13
|
-
|
14
|
-
def sync
|
15
|
-
dirty = false
|
16
|
-
gdoc_tab_language = gdoc_trans_reader.build_trans_hash(language)
|
17
|
-
file = gdoc_tab_language[:title]
|
18
|
-
|
19
|
-
new_xliff_hash = {
|
20
|
-
language: language,
|
21
|
-
file: file,
|
22
|
-
translations: []
|
23
|
-
}
|
24
|
-
|
25
|
-
xliff_for_language = xliff_translations.detect{ |x| x[:language] == language }[:translations]
|
26
|
-
gdoc_tab_language[:translations].each do |gdoc_trans|
|
27
|
-
x_trans = xliff_for_language.detect{ |x| x[:key] == gdoc_trans[:key] }
|
28
|
-
|
29
|
-
# whole key is missing
|
30
|
-
if x_trans.nil?
|
31
|
-
SyncUtil.info_diff(file, language, 'Adding', gdoc_trans)
|
32
|
-
|
33
|
-
new_xliff_hash[:translations] << gdoc_trans
|
34
|
-
dirty = true
|
35
|
-
elsif gdoc_trans[:value] != x_trans[:value]
|
36
|
-
SyncUtil.info_diff(file, language, 'Changing', gdoc_trans)
|
37
|
-
|
38
|
-
x_trans[:value] = gdoc_trans[:value]
|
39
|
-
new_xliff_hash[:translations] << x_trans
|
40
|
-
dirty = true
|
41
|
-
else
|
42
|
-
# nothing new
|
43
|
-
new_xliff_hash[:translations] << gdoc_trans
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
return dirty, new_xliff_hash
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require_relative '../gdoc_trans/gdoc_trans_reader'
|
3
|
-
require_relative '../gdoc_trans/gdoc_trans_writer'
|
4
|
-
require_relative 'xliff_to_gdoc'
|
5
|
-
require_relative 'sync_util'
|
6
|
-
|
7
|
-
class Xliff2GdocMain
|
8
|
-
attr_reader :path, :config
|
9
|
-
|
10
|
-
def initialize(path)
|
11
|
-
@path = path
|
12
|
-
@config = GdocTrans::CONFIG
|
13
|
-
SyncUtil.create_logger('xliff2gdoc')
|
14
|
-
end
|
15
|
-
|
16
|
-
def run
|
17
|
-
@config['FILES'].each do |file|
|
18
|
-
xliff_translations = SyncUtil::check_and_get_xliff_files(@config['LANGUAGES'], path, file)
|
19
|
-
|
20
|
-
gdoc_trans_reader = GdocTransReader.new(@config['GDOC'], file)
|
21
|
-
gdoc_trans_writer = GdocTransWriter.new(gdoc_trans_reader.worksheet)
|
22
|
-
|
23
|
-
@config['LANGUAGES'].each do |language|
|
24
|
-
options = {
|
25
|
-
xliff_translations: xliff_translations,
|
26
|
-
gdoc_trans_reader: gdoc_trans_reader,
|
27
|
-
gdoc_trans_writer: gdoc_trans_writer,
|
28
|
-
language: language,
|
29
|
-
languages: @config['LANGUAGES']
|
30
|
-
}
|
31
|
-
xliff_to_gdoc = XliffToGdoc.new(options)
|
32
|
-
dirty = xliff_to_gdoc.sync
|
33
|
-
|
34
|
-
# save it back on google drive
|
35
|
-
gdoc_trans_writer.worksheet.save if dirty
|
36
|
-
SyncUtil.info_clean(file, language, 'was clean. Already has same keys and values inside GDoc') unless dirty
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require_relative 'sync_util'
|
2
|
-
|
3
|
-
class XliffToGdoc
|
4
|
-
attr_accessor :xliff_translations,
|
5
|
-
:gdoc_trans_reader,
|
6
|
-
:gdoc_trans_writer,
|
7
|
-
:language,
|
8
|
-
:languages,
|
9
|
-
:logger
|
10
|
-
|
11
|
-
def initialize(options = {})
|
12
|
-
self.xliff_translations = options[:xliff_translations]
|
13
|
-
self.gdoc_trans_reader = options[:gdoc_trans_reader]
|
14
|
-
self.gdoc_trans_writer = options[:gdoc_trans_writer]
|
15
|
-
self.language = options[:language]
|
16
|
-
self.languages = options[:languages]
|
17
|
-
end
|
18
|
-
|
19
|
-
def sync
|
20
|
-
gdoc_tab_language = gdoc_trans_reader.build_trans_hash(language)
|
21
|
-
dirty = false
|
22
|
-
file = gdoc_tab_language[:title]
|
23
|
-
|
24
|
-
xliff_for_language = xliff_translations.detect{ |x| x[:language] == language }
|
25
|
-
xliff_for_language[:translations].each_with_index do |x_trans, index|
|
26
|
-
|
27
|
-
# for current xliff translation find the same trans key in google doc
|
28
|
-
gdoc_trans = gdoc_tab_language[:translations].detect{ |g_trans| g_trans[:key] == x_trans[:key] }
|
29
|
-
current_row = index + GdocTrans::START_ROW
|
30
|
-
|
31
|
-
# whole key is missing
|
32
|
-
if gdoc_trans.nil?
|
33
|
-
# heavy coupling
|
34
|
-
gdoc_trans_reader.worksheet = gdoc_trans_writer.shift_up(current_row, xliff_for_language[:translations].length)
|
35
|
-
# recalculate hashes after shift
|
36
|
-
gdoc_tab_language = gdoc_trans_reader.build_trans_hash(language)
|
37
|
-
|
38
|
-
gdoc_trans_writer.write(current_row, 'key', x_trans[:key])
|
39
|
-
gdoc_trans_writer.write(current_row, language, x_trans[:value])
|
40
|
-
|
41
|
-
SyncUtil.info_diff(file, language, 'Adding', x_trans)
|
42
|
-
|
43
|
-
# Go for all other languages if key was missing
|
44
|
-
languages.each do |key_lang|
|
45
|
-
next if key_lang == language
|
46
|
-
|
47
|
-
xliff_lang = xliff_translations.detect{ |xt| xt[:language] == key_lang }
|
48
|
-
xliff_lang_value = xliff_lang[:translations].detect{ |xt| xt[:key] == x_trans[:key] }
|
49
|
-
|
50
|
-
gdoc_trans_writer.write(current_row, key_lang, xliff_lang_value[:value])
|
51
|
-
end
|
52
|
-
|
53
|
-
dirty = true
|
54
|
-
elsif gdoc_trans[:value] != x_trans[:value]
|
55
|
-
gdoc_trans_writer.write(current_row, language, x_trans[:value])
|
56
|
-
SyncUtil.info_diff(file, language, 'Changing', x_trans)
|
57
|
-
dirty = true
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
dirty
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|