2014-04-14 23:41:36 +08:00
|
|
|
# This script pulls translation files from Transifex and ensures they are in the format we need.
|
|
|
|
# You need the Transifex client installed.
|
|
|
|
# http://docs.transifex.com/developer/client/setup
|
|
|
|
#
|
|
|
|
# Don't use this script to create pull requests. Do translations in Transifex. The Discourse
|
|
|
|
# team will pull them in.
|
|
|
|
|
|
|
|
require 'open3'
|
2015-09-19 04:30:28 +08:00
|
|
|
require_relative '../lib/locale_file_walker'
|
2014-04-14 23:41:36 +08:00
|
|
|
|
|
|
|
if `which tx`.strip.empty?
|
2015-05-01 04:27:05 +08:00
|
|
|
puts '', 'The Transifex client needs to be installed to use this script.'
|
|
|
|
puts 'Instructions are here: http://docs.transifex.com/developer/client/setup'
|
|
|
|
puts '', 'On Mac:', ''
|
|
|
|
puts ' curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py'
|
|
|
|
puts ' sudo python get-pip.py'
|
|
|
|
puts ' sudo pip install transifex-client', ''
|
2014-04-14 23:41:36 +08:00
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
|
2015-09-19 04:30:28 +08:00
|
|
|
languages = Dir.glob(File.expand_path('../../config/locales/client.*.yml', __FILE__))
|
|
|
|
.map { |x| x.split('.')[-2] }.select { |x| x != 'en' }.sort
|
2014-04-16 22:35:27 +08:00
|
|
|
|
2015-05-01 04:27:05 +08:00
|
|
|
puts 'Pulling new translations...', ''
|
2015-09-19 04:30:28 +08:00
|
|
|
command = "tx pull --mode=developer --language=#{languages.join(',')} #{ARGV.include?('force') ? '-f' : ''}"
|
2014-04-16 22:35:27 +08:00
|
|
|
|
|
|
|
Open3.popen2e(command) do |stdin, stdout_err, wait_thr|
|
2015-05-01 04:27:05 +08:00
|
|
|
while (line = stdout_err.gets)
|
2014-04-14 23:41:36 +08:00
|
|
|
puts line
|
|
|
|
end
|
|
|
|
end
|
2015-05-01 04:27:05 +08:00
|
|
|
puts ''
|
2014-04-14 23:41:36 +08:00
|
|
|
|
2014-04-16 22:35:27 +08:00
|
|
|
unless $?.success?
|
2015-05-01 04:27:05 +08:00
|
|
|
puts 'Something failed. Check the output above.', ''
|
2014-04-14 23:41:36 +08:00
|
|
|
exit $?.exitstatus
|
|
|
|
end
|
|
|
|
|
2014-04-24 22:11:23 +08:00
|
|
|
YML_FILE_COMMENTS = <<END
|
2014-04-14 23:41:36 +08:00
|
|
|
# encoding: utf-8
|
|
|
|
#
|
|
|
|
# Never edit this file. It will be overwritten when translations are pulled from Transifex.
|
|
|
|
#
|
|
|
|
# To work with us on translations, join this project:
|
2014-05-21 00:54:19 +08:00
|
|
|
# https://www.transifex.com/projects/p/discourse-org/
|
2014-04-14 23:41:36 +08:00
|
|
|
END
|
|
|
|
|
2014-04-24 22:11:23 +08:00
|
|
|
YML_DIRS = ['config/locales',
|
|
|
|
'plugins/poll/config/locales',
|
|
|
|
'vendor/gems/discourse_imgur/lib/discourse_imgur/locale']
|
2015-09-19 04:30:28 +08:00
|
|
|
YML_FILE_PREFIXES = ['server', 'client']
|
2014-04-24 22:11:23 +08:00
|
|
|
|
2015-09-19 04:30:28 +08:00
|
|
|
def yml_path(dir, prefix, language)
|
|
|
|
path = "../../#{dir}/#{prefix}.#{language}.yml"
|
|
|
|
path = File.expand_path(path, __FILE__)
|
|
|
|
File.exists?(path) ? path : nil
|
|
|
|
end
|
|
|
|
|
|
|
|
# Add comments to the top of files and replace the language (first key in YAML file)
|
|
|
|
def update_file_header(filename, language)
|
|
|
|
lines = File.readlines(filename)
|
|
|
|
lines.collect! {|line| line =~ /^[a-z_]+:$/i ? "#{language}:" : line}
|
|
|
|
|
|
|
|
File.open(filename, 'w+') do |f|
|
|
|
|
f.puts(YML_FILE_COMMENTS, '') unless lines[0][0] == '#'
|
|
|
|
f.puts(lines)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class YamlAliasFinder < LocaleFileWalker
|
|
|
|
def initialize
|
|
|
|
@anchors = {}
|
|
|
|
@aliases = Hash.new { |hash, key| hash[key] = [] }
|
|
|
|
end
|
|
|
|
|
|
|
|
def parse_file(filename)
|
|
|
|
document = Psych.parse_file(filename)
|
|
|
|
handle_document(document)
|
|
|
|
{anchors: @anchors, aliases: @aliases}
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def handle_alias(node, depth, parents)
|
|
|
|
@aliases[node.anchor] << parents.dup
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_mapping(node, depth, parents)
|
|
|
|
if node.anchor
|
|
|
|
@anchors[parents.dup] = node.anchor
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class YamlAliasSynchronizer < LocaleFileWalker
|
|
|
|
def initialize(original_alias_data)
|
|
|
|
@anchors = original_alias_data[:anchors]
|
|
|
|
@aliases = original_alias_data[:aliases]
|
|
|
|
@used_anchors = Set.new
|
|
|
|
|
|
|
|
calculate_required_keys
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_to(filename)
|
|
|
|
stream = Psych.parse_stream(File.read(filename))
|
|
|
|
stream.children.each { |document| handle_document(document) }
|
|
|
|
|
|
|
|
add_aliases
|
|
|
|
write_yaml(stream, filename)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def calculate_required_keys
|
|
|
|
@required_keys = {}
|
|
|
|
|
|
|
|
@aliases.each_value do |key_sets|
|
|
|
|
key_sets.each do |keys|
|
|
|
|
until keys.empty?
|
|
|
|
add_needed_node(keys)
|
|
|
|
keys = keys.dup
|
|
|
|
keys.pop
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
add_needed_node([]) unless @required_keys.empty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_needed_node(keys)
|
|
|
|
@required_keys[keys] = {mapping: nil, scalar: nil, alias: nil}
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_yaml(stream, filename)
|
|
|
|
yaml = stream.to_yaml(nil, {:line_width => -1})
|
|
|
|
|
|
|
|
File.open(filename, 'w') do |file|
|
|
|
|
file.write(yaml)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_scalar(node, depth, parents)
|
|
|
|
super(node, depth, parents)
|
|
|
|
|
|
|
|
if @required_keys.has_key?(parents)
|
|
|
|
@required_keys[parents][:scalar] = node
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_alias(node, depth, parents)
|
|
|
|
if @required_keys.has_key?(parents)
|
|
|
|
@required_keys[parents][:alias] = node
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_mapping(node, depth, parents)
|
|
|
|
if @anchors.has_key?(parents)
|
|
|
|
node.anchor = @anchors[parents]
|
|
|
|
@used_anchors.add(node.anchor)
|
|
|
|
end
|
|
|
|
|
|
|
|
if @required_keys.has_key?(parents)
|
|
|
|
@required_keys[parents][:mapping] = node
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_aliases
|
|
|
|
@used_anchors.each do |anchor|
|
|
|
|
@aliases[anchor].each do |keys|
|
|
|
|
parents = []
|
|
|
|
parent_node = @required_keys[[]]
|
|
|
|
|
|
|
|
keys.each_with_index do |key, index|
|
|
|
|
parents << key
|
|
|
|
current_node = @required_keys[parents]
|
|
|
|
is_last = index == keys.size - 1
|
|
|
|
add_node(current_node, parent_node, key, is_last ? anchor : nil)
|
|
|
|
parent_node = current_node
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_node(node, parent_node, scalar_name, anchor)
|
|
|
|
parent_mapping = parent_node[:mapping]
|
|
|
|
parent_mapping.children ||= []
|
|
|
|
|
|
|
|
if node[:scalar].nil?
|
|
|
|
node[:scalar] = Psych::Nodes::Scalar.new(scalar_name)
|
|
|
|
parent_mapping.children << node[:scalar]
|
|
|
|
end
|
|
|
|
|
|
|
|
if anchor.nil?
|
|
|
|
if node[:mapping].nil?
|
|
|
|
node[:mapping] = Psych::Nodes::Mapping.new
|
|
|
|
parent_mapping.children << node[:mapping]
|
|
|
|
end
|
|
|
|
elsif node[:alias].nil?
|
|
|
|
parent_mapping.children << Psych::Nodes::Alias.new(anchor)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_english_alias_data(dir, prefix)
|
|
|
|
filename = yml_path(dir, prefix, 'en')
|
|
|
|
filename ? YamlAliasFinder.new.parse_file(filename) : nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_anchors_and_aliases(english_alias_data, filename)
|
|
|
|
if english_alias_data
|
|
|
|
YamlAliasSynchronizer.new(english_alias_data).add_to(filename)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
YML_DIRS.each do |dir|
|
|
|
|
YML_FILE_PREFIXES.each do |prefix|
|
|
|
|
english_alias_data = get_english_alias_data(dir, prefix)
|
2015-05-06 23:03:07 +08:00
|
|
|
|
2015-09-19 04:30:28 +08:00
|
|
|
languages.each do |language|
|
|
|
|
filename = yml_path(dir, prefix, language)
|
2015-05-06 23:03:07 +08:00
|
|
|
|
2015-09-19 04:30:28 +08:00
|
|
|
if filename
|
|
|
|
add_anchors_and_aliases(english_alias_data, filename)
|
|
|
|
update_file_header(filename, language)
|
2014-04-24 22:11:23 +08:00
|
|
|
end
|
2014-04-14 23:41:36 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|