Compare commits
4 commits
organicmap
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
46a250b46b | ||
|
4ac26c5616 | ||
|
504f3548ac | ||
|
1813945b2d |
9 changed files with 153 additions and 9 deletions
|
@ -31,6 +31,7 @@ module Twine
|
||||||
require 'twine/formatters/abstract'
|
require 'twine/formatters/abstract'
|
||||||
require 'twine/formatters/android'
|
require 'twine/formatters/android'
|
||||||
require 'twine/formatters/apple'
|
require 'twine/formatters/apple'
|
||||||
|
require 'twine/formatters/apple_plural'
|
||||||
require 'twine/formatters/django'
|
require 'twine/formatters/django'
|
||||||
require 'twine/formatters/flash'
|
require 'twine/formatters/flash'
|
||||||
require 'twine/formatters/gettext'
|
require 'twine/formatters/gettext'
|
||||||
|
|
|
@ -3,6 +3,7 @@ require 'fileutils'
|
||||||
module Twine
|
module Twine
|
||||||
module Formatters
|
module Formatters
|
||||||
class Abstract
|
class Abstract
|
||||||
|
SUPPORTS_PLURAL = false
|
||||||
attr_accessor :twine_file
|
attr_accessor :twine_file
|
||||||
attr_accessor :options
|
attr_accessor :options
|
||||||
|
|
||||||
|
@ -132,7 +133,13 @@ module Twine
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_definition(definition, lang)
|
def format_definition(definition, lang)
|
||||||
[format_comment(definition, lang), format_key_value(definition, lang)].compact.join
|
formatted_definition = [format_comment(definition, lang)]
|
||||||
|
if self.class::SUPPORTS_PLURAL && definition.is_plural?
|
||||||
|
formatted_definition << format_plural(definition, lang)
|
||||||
|
else
|
||||||
|
formatted_definition << format_key_value(definition, lang)
|
||||||
|
end
|
||||||
|
formatted_definition.compact.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_comment(definition, lang)
|
def format_comment(definition, lang)
|
||||||
|
@ -143,10 +150,21 @@ module Twine
|
||||||
key_value_pattern % { key: format_key(definition.key.dup), value: format_value(value.dup) }
|
key_value_pattern % { key: format_key(definition.key.dup), value: format_value(value.dup) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_plural(definition, lang)
|
||||||
|
plural_hash = definition.plural_translation_for_lang(lang)
|
||||||
|
if plural_hash
|
||||||
|
format_plural_keys(definition.key.dup, plural_hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def key_value_pattern
|
def key_value_pattern
|
||||||
raise NotImplementedError.new("You must implement key_value_pattern in your formatter class.")
|
raise NotImplementedError.new("You must implement key_value_pattern in your formatter class.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_plural_keys(key, plural_hash)
|
||||||
|
raise NotImplementedError.new("You must implement format_plural_keys in your formatter class.")
|
||||||
|
end
|
||||||
|
|
||||||
def format_key(key)
|
def format_key(key)
|
||||||
key
|
key
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,15 @@ module Twine
|
||||||
class Android < Abstract
|
class Android < Abstract
|
||||||
include Twine::Placeholders
|
include Twine::Placeholders
|
||||||
|
|
||||||
|
SUPPORTS_PLURAL = true
|
||||||
|
LANG_CODES = Hash[
|
||||||
|
'zh' => 'zh-Hans',
|
||||||
|
'zh-CN' => 'zh-Hans',
|
||||||
|
'zh-HK' => 'zh-Hant',
|
||||||
|
'en-GB' => 'en-GB',
|
||||||
|
'in' => 'id'
|
||||||
|
]
|
||||||
|
|
||||||
def format_name
|
def format_name
|
||||||
'android'
|
'android'
|
||||||
end
|
end
|
||||||
|
@ -33,7 +42,10 @@ module Twine
|
||||||
# see http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources
|
# see http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources
|
||||||
match = /^values-([a-z]{2}(-r[a-z]{2})?)$/i.match(segment)
|
match = /^values-([a-z]{2}(-r[a-z]{2})?)$/i.match(segment)
|
||||||
|
|
||||||
return match[1].sub('-r', '-') if match
|
if match
|
||||||
|
lang = match[1].sub('-r', '-')
|
||||||
|
return LANG_CODES.fetch(lang, lang)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,6 +111,12 @@ module Twine
|
||||||
"\t<string name=\"%{key}\">%{value}</string>"
|
"\t<string name=\"%{key}\">%{value}</string>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_plural_keys(key, plural_hash)
|
||||||
|
result = "\t<plurals name=\"#{key}\">\n"
|
||||||
|
result += plural_hash.map{|quantity,value| "\t#{' ' * 2}<item quantity=\"#{quantity}\">#{value}</item>"}.join("\n")
|
||||||
|
result += "\n\t</plurals>"
|
||||||
|
end
|
||||||
|
|
||||||
def gsub_unless(text, pattern, replacement)
|
def gsub_unless(text, pattern, replacement)
|
||||||
text.gsub(pattern) do |match|
|
text.gsub(pattern) do |match|
|
||||||
match_start_position = Regexp.last_match.offset(0)[0]
|
match_start_position = Regexp.last_match.offset(0)[0]
|
||||||
|
|
|
@ -86,6 +86,10 @@ module Twine
|
||||||
def format_value(value)
|
def format_value(value)
|
||||||
escape_quotes(value)
|
escape_quotes(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def should_include_definition(definition, lang)
|
||||||
|
return !definition.is_plural? && super
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
68
lib/twine/formatters/apple_plural.rb
Normal file
68
lib/twine/formatters/apple_plural.rb
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
module Twine
|
||||||
|
module Formatters
|
||||||
|
class ApplePlural < Apple
|
||||||
|
SUPPORTS_PLURAL = true
|
||||||
|
|
||||||
|
def format_name
|
||||||
|
'apple-plural'
|
||||||
|
end
|
||||||
|
|
||||||
|
def extension
|
||||||
|
'.stringsdict'
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_file_name
|
||||||
|
'Localizable.stringsdict'
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_footer(lang)
|
||||||
|
footer = "</dict>\n</plist>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_file(lang)
|
||||||
|
result = super
|
||||||
|
result += format_footer(lang)
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_header(lang)
|
||||||
|
header = "<!--\n * Apple Stringsdict File\n * Generated by Twine #{Twine::VERSION}\n * Language: #{lang} -->\n"
|
||||||
|
header += "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n"
|
||||||
|
header += "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
||||||
|
header += "<plist version=\"1.0\">\n<dict>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_section_header(section)
|
||||||
|
"<!-- ********** #{section.name} **********/ -->\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_plural_keys(key, plural_hash)
|
||||||
|
result = "#{tab(2)}<key>#{key}</key>\n"
|
||||||
|
result += "#{tab(2)}<dict>\n"
|
||||||
|
result += "#{tab(4)}<key>NSStringLocalizedFormatKey</key>\n#{tab(4)}<string>\%\#@value@</string>\n"
|
||||||
|
result += "#{tab(4)}<key>value</key>\n#{tab(4)}<dict>\n"
|
||||||
|
result += "#{tab(6)}<key>NSStringFormatSpecTypeKey</key>\n#{tab(6)}<string>NSStringPluralRuleType</string>\n"
|
||||||
|
result += "#{tab(6)}<key>NSStringFormatValueTypeKey</key>\n#{tab(6)}<string>d</string>\n"
|
||||||
|
result += plural_hash.map{|quantity,value| "#{tab(6)}<key>#{quantity}</key>\n#{tab(6)}<string>#{value}</string>"}.join("\n")
|
||||||
|
result += "\n#{tab(4)}</dict>\n#{tab(2)}</dict>\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_comment(definition, lang)
|
||||||
|
"<!-- #{definition.comment.gsub('--', '—')} -->\n" if definition.comment
|
||||||
|
end
|
||||||
|
|
||||||
|
def read(io, lang)
|
||||||
|
raise NotImplementedError.new("Reading \".stringdict\" files not implemented yet")
|
||||||
|
end
|
||||||
|
|
||||||
|
def tab(level)
|
||||||
|
' ' * level
|
||||||
|
end
|
||||||
|
|
||||||
|
def should_include_definition(definition, lang)
|
||||||
|
return definition.is_plural? && definition.plural_translation_for_lang(lang)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Twine::Formatters.formatters << Twine::Formatters::ApplePlural.new
|
|
@ -16,9 +16,9 @@ module Twine
|
||||||
def determine_language_given_path(path)
|
def determine_language_given_path(path)
|
||||||
path_arr = path.split(File::SEPARATOR)
|
path_arr = path.split(File::SEPARATOR)
|
||||||
path_arr.each do |segment|
|
path_arr.each do |segment|
|
||||||
match = /^((.+)-)?([^-]+)\.json$/.match(segment)
|
match = /^(.+)\.json$/.match(segment)
|
||||||
if match
|
if match
|
||||||
return match[3]
|
return match[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,14 @@ module Twine
|
||||||
new_definition = definition.dup
|
new_definition = definition.dup
|
||||||
new_definition.translations[language] = value
|
new_definition.translations[language] = value
|
||||||
|
|
||||||
|
if definition.is_plural?
|
||||||
|
# If definition is plural, but no translation found -> create
|
||||||
|
# Then check 'other' key
|
||||||
|
if !(new_definition.plural_translations[language] ||= {}).key? 'other'
|
||||||
|
new_definition.plural_translations[language]['other'] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
new_section.definitions << new_definition
|
new_section.definitions << new_definition
|
||||||
result.definitions_by_key[new_definition.key] = new_definition
|
result.definitions_by_key[new_definition.key] = new_definition
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
module Twine
|
module Twine
|
||||||
class TwineDefinition
|
class TwineDefinition
|
||||||
|
PLURAL_KEYS = %w(zero one two few many other)
|
||||||
|
|
||||||
attr_reader :key
|
attr_reader :key
|
||||||
attr_accessor :comment
|
attr_accessor :comment
|
||||||
attr_accessor :tags
|
attr_accessor :tags
|
||||||
attr_reader :translations
|
attr_reader :translations
|
||||||
|
attr_reader :plural_translations
|
||||||
|
attr_reader :is_plural
|
||||||
attr_accessor :reference
|
attr_accessor :reference
|
||||||
attr_accessor :reference_key
|
attr_accessor :reference_key
|
||||||
|
|
||||||
|
@ -12,6 +16,7 @@ module Twine
|
||||||
@comment = nil
|
@comment = nil
|
||||||
@tags = nil
|
@tags = nil
|
||||||
@translations = {}
|
@translations = {}
|
||||||
|
@plural_translations = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def comment
|
def comment
|
||||||
|
@ -50,6 +55,16 @@ module Twine
|
||||||
|
|
||||||
return translation
|
return translation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def plural_translation_for_lang(lang)
|
||||||
|
if @plural_translations.has_key? lang
|
||||||
|
@plural_translations[lang].dup
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_plural?
|
||||||
|
!@plural_translations.empty?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class TwineSection
|
class TwineSection
|
||||||
|
@ -137,11 +152,12 @@ module Twine
|
||||||
parsed = true
|
parsed = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
match = /^([^=]+)=(.*)$/.match(line)
|
match = /^([^:=]+)(?::([^=]+))?=(.*)$/.match(line)
|
||||||
if match
|
if match
|
||||||
key = match[1].strip
|
key = match[1].strip
|
||||||
value = match[2].strip
|
plural_key = match[2].to_s.strip
|
||||||
|
value = match[3].strip
|
||||||
|
|
||||||
value = value[1..-2] if value[0] == '`' && value[-1] == '`'
|
value = value[1..-2] if value[0] == '`' && value[-1] == '`'
|
||||||
|
|
||||||
case key
|
case key
|
||||||
|
@ -155,7 +171,18 @@ module Twine
|
||||||
if !@language_codes.include? key
|
if !@language_codes.include? key
|
||||||
add_language_code(key)
|
add_language_code(key)
|
||||||
end
|
end
|
||||||
current_definition.translations[key] = value
|
# Providing backward compatibility
|
||||||
|
# for formatters without plural support
|
||||||
|
if plural_key.empty? || plural_key == 'other'
|
||||||
|
current_definition.translations[key] = value
|
||||||
|
end
|
||||||
|
if !plural_key.empty?
|
||||||
|
if !TwineDefinition::PLURAL_KEYS.include? plural_key
|
||||||
|
warn("Unknown plural key #{plural_key}")
|
||||||
|
next
|
||||||
|
end
|
||||||
|
(current_definition.plural_translations[key] ||= {})[plural_key] = value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
parsed = true
|
parsed = true
|
||||||
end
|
end
|
||||||
|
|
2
twine
2
twine
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
BASEDIR=$(dirname $0)
|
BASEDIR=$(dirname $0)
|
||||||
ruby -rubygems -I $BASEDIR/lib $BASEDIR/bin/twine "$@"
|
ruby -rrubygems -I $BASEDIR/lib $BASEDIR/bin/twine "$@"
|
||||||
|
|
Reference in a new issue