Class: I18nContextGenerator::LocalizationSyntax

Inherits:
Object
  • Object
show all
Defined in:
lib/i18n_context_generator/localization_syntax.rb

Overview

Registry of localization call/resource syntaxes shared by source search, source-first discovery, and Swift comment write-back.

Constant Summary collapse

DEFAULT_SWIFT_FUNCTIONS =
%w[
  NSLocalizedString
  String(localized:
  Text(
  LocalizedStringResource(
].freeze
IOS_STATIC_SEARCH_BUILDERS =
[
  ->(key) { "LocalizedStringKey\\s*\\(\\s*\"#{key}\"" },
  ->(key) { "LocalizedStringKey\\s*=\\s*\"#{key}\"" },
  ->(key) { ":\\s*LocalizedStringResource\\s*=\\s*\"#{key}\"" },
  ->(key) { "\"#{key}\"\\.localized" }
].freeze
IOS_STATIC_SINGLE_LINE_DISCOVERY_PATTERNS =
[
  /LocalizedStringKey\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"\s*\)/,
  /:\s*LocalizedStringKey\s*=\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"/,
  /:\s*LocalizedStringResource\s*=\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"/,
  /"(?<key>#{SWIFT_STRING_BODY_PATTERN})"\.localized\b/
].freeze
LOCALIZED_RESOURCE_SINGLE_LINE_DISCOVERY_PATTERNS =
[
  /LocalizedStringResource\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"[^\n]*?\bdefaultValue:\s*"(?<text>#{SWIFT_STRING_BODY_PATTERN})"/,
  /LocalizedStringResource\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"/
].freeze
IOS_STATIC_MULTILINE_DISCOVERY_PATTERNS =
[
  /Text\s*\(\s*LocalizedStringKey\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"\s*\)[\s\S]*?\)/
].freeze
LOCALIZED_RESOURCE_MULTILINE_DISCOVERY_PATTERNS =
[
  /LocalizedStringResource\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"[\s\S]*?\bdefaultValue:\s*"(?<text>#{SWIFT_STRING_BODY_PATTERN})"/,
  /LocalizedStringResource\s*\(\s*"(?<key>#{SWIFT_STRING_BODY_PATTERN})"/
].freeze
ANDROID_DISCOVERY_PATTERNS =
{
  string: %r{R\.string\.(\w+)\b|@string/([\w.]+)\b|[(\s,=]string\.(\w+)\b}x,
  plural: %r{R\.plurals\.(\w+)\b|@plurals/([\w.]+)\b|[(\s,=]plurals\.(\w+)\b}x,
  array: %r{R\.array\.(\w+)\b|@array/([\w.]+)\b|[(\s,=]array\.(\w+)\b}x
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(swift_functions: nil) ⇒ LocalizationSyntax

Returns a new instance of LocalizationSyntax.



75
76
77
# File 'lib/i18n_context_generator/localization_syntax.rb', line 75

def initialize(swift_functions: nil)
  @swift_functions = self.class.functions_with_defaults(swift_functions)
end

Instance Attribute Details

#swift_functionsObject (readonly)

Returns the value of attribute swift_functions.



79
80
81
# File 'lib/i18n_context_generator/localization_syntax.rb', line 79

def swift_functions
  @swift_functions
end

Class Method Details

.functions_with_defaults(functions) ⇒ Object



56
57
58
59
# File 'lib/i18n_context_generator/localization_syntax.rb', line 56

def self.functions_with_defaults(functions)
  configured = Array(functions).map(&:strip).reject(&:empty?)
  (DEFAULT_SWIFT_FUNCTIONS + configured).uniq { |function| function.sub(/\(\s*\z/, '') }.freeze
end

.swift_string_content_pattern(value) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/i18n_context_generator/localization_syntax.rb', line 61

def self.swift_string_content_pattern(value)
  encoded = value.each_char.map do |character|
    case character
    when '\\' then '\\\\'
    when '"' then '\\"'
    when "\n" then '\n'
    when "\r" then '\r'
    when "\t" then '\t'
    else character
    end
  end.join
  Regexp.escape(encoded)
end

Instance Method Details

#android_discovery_patternsObject



143
144
145
# File 'lib/i18n_context_generator/localization_syntax.rb', line 143

def android_discovery_patterns
  ANDROID_DISCOVERY_PATTERNS
end

#android_search_patterns(key, resource_type: nil) ⇒ Object



103
104
105
106
107
108
109
110
111
112
# File 'lib/i18n_context_generator/localization_syntax.rb', line 103

def android_search_patterns(key, resource_type: nil)
  base_key = AndroidResource.base_key(key)
  escaped_base = Regexp.escape(base_key)

  case AndroidResource.type_for(key, explicit: resource_type)
  when :plural then android_plural_patterns(escaped_base)
  when :array then android_array_patterns(escaped_base)
  else android_string_patterns(Regexp.escape(key))
  end
end

#ios_call_start_patternsObject



128
129
130
131
# File 'lib/i18n_context_generator/localization_syntax.rb', line 128

def ios_call_start_patterns
  @ios_call_start_patterns ||=
    @swift_functions.map { |function| Regexp.new(swift_function_opener(function)) }.freeze
end

#ios_multiline_discovery_patternsObject



121
122
123
124
125
126
# File 'lib/i18n_context_generator/localization_syntax.rb', line 121

def ios_multiline_discovery_patterns
  @ios_multiline_discovery_patterns ||=
    (LOCALIZED_RESOURCE_MULTILINE_DISCOVERY_PATTERNS +
      function_discovery_patterns(multiline: true) +
      IOS_STATIC_MULTILINE_DISCOVERY_PATTERNS).freeze
end

#ios_multiline_search_patterns(key) ⇒ Object



98
99
100
101
# File 'lib/i18n_context_generator/localization_syntax.rb', line 98

def ios_multiline_search_patterns(key)
  escaped_key = self.class.swift_string_content_pattern(key)
  swift_function_key_patterns(escaped_key).map { |pattern| Regexp.new(pattern) }
end

#ios_search_patterns(key) ⇒ Object



92
93
94
95
96
# File 'lib/i18n_context_generator/localization_syntax.rb', line 92

def ios_search_patterns(key)
  escaped_key = self.class.swift_string_content_pattern(key)
  function_patterns = swift_function_key_patterns(escaped_key)
  function_patterns + IOS_STATIC_SEARCH_BUILDERS.map { |builder| builder.call(escaped_key) }
end

#ios_single_line_discovery_patternsObject



114
115
116
117
118
119
# File 'lib/i18n_context_generator/localization_syntax.rb', line 114

def ios_single_line_discovery_patterns
  @ios_single_line_discovery_patterns ||=
    (LOCALIZED_RESOURCE_SINGLE_LINE_DISCOVERY_PATTERNS +
      function_discovery_patterns(multiline: false) +
      IOS_STATIC_SINGLE_LINE_DISCOVERY_PATTERNS).freeze
end

#ios_wrapper_definition_patternObject



133
134
135
136
137
138
139
140
141
# File 'lib/i18n_context_generator/localization_syntax.rb', line 133

def ios_wrapper_definition_pattern
  @ios_wrapper_definition_pattern ||= begin
    functions = (@swift_functions.map { |function| swift_call_prefix(function) } +
      ['LocalizedStringKey\\s*\\(']).join('|')
    constructor = "\\s*=\\s*(?:#{functions})"
    typed_resource = '\s*:\s*LocalizedStringResource\s*=\s*"'
    /\bstatic\s+(?:let|var)\s+(?<member_name>\w+)(?:#{constructor}|#{typed_resource})/
  end
end

#search_patterns(key, platform:, resource_type: nil) ⇒ Object



81
82
83
84
85
86
87
88
89
90
# File 'lib/i18n_context_generator/localization_syntax.rb', line 81

def search_patterns(key, platform:, resource_type: nil)
  strings = case platform.to_sym
            when :ios then ios_search_patterns(key)
            when :android then android_search_patterns(key, resource_type: resource_type)
            else
              ios_search_patterns(key) + android_search_patterns(key, resource_type: resource_type) +
              [Regexp.escape(key)]
            end
  strings.map { |pattern| Regexp.new(pattern) }
end

#swift_writer_patterns(key) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/i18n_context_generator/localization_syntax.rb', line 147

def swift_writer_patterns(key)
  escaped_key = self.class.swift_string_content_pattern(key)
  comment = 'comment:\\s*"(?:\\\\.|[^"\\\\])*"'

  patterns = @swift_functions.map do |function|
    Regexp.new(
      "#{swift_key_argument_prefix(function)}\"#{escaped_key}\"[^)]*#{comment}[^)]*\\)",
      Regexp::MULTILINE
    )
  end
  patterns << nested_text_writer_pattern(escaped_key, comment)
  patterns
end