Skip to content

Commit

Permalink
Implementing new Swifternalization class - WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkowz committed Jul 31, 2015
1 parent e00c3db commit 9b24d42
Show file tree
Hide file tree
Showing 23 changed files with 162 additions and 984 deletions.
162 changes: 41 additions & 121 deletions Swifternalization.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

128 changes: 37 additions & 91 deletions Swifternalization/Expression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,128 +2,74 @@
// Expression.swift
// Swifternalization
//
// Created by Tomasz Szulc on 27/06/15.
// Created by Tomasz Szulc on 26/07/15.
// Copyright (c) 2015 Tomasz Szulc. All rights reserved.
//

import Foundation

/// String that contains expression pattern, e.g. `ie:x<5`, `exp:^1$`.
internal typealias ExpressionPattern = String
typealias ExpressionPattern = String

/**
Class represents single expression that is added in curly
brackets inside key in Localizable.strings file or as a value in
Expressions.strings file.

It is able to validate passed string using internal expression matcher.
Represents simple epxressions.
*/
class Expression {
/// Pattern of expression passed during initialization.
let pattern: ExpressionPattern

/// Type of expression computed based on `pattern`.
private var type: ExpressionPatternType!

/// Matcher created based on `pattern`.
private var matcher: ExpressionMatcher!

/**
Return `ExpressionPattern` object if passed `str` parameter contains
some pattern. The pattern may not be one of the supported one.
If the syntax of the passed string is correct it is treated as pattern.
struct Expression {
/// Pattern of expression.
let pattern: String

:param: str string which may or may not contain a pattern.
:returns: `ExpressionPattern` object or nil when pattern is not found.
*/
class func parseExpressionPattern(str: String) -> ExpressionPattern? {
if let pattern = Regex.firstMatchInString(str, pattern: InternalPattern.Expression.rawValue) {
return pattern
} else {
// println("Cannot get expression pattern from string: \(str).")
return nil
}
}
/// A localized value. If `lengthVariations` array is empty or you want to
/// get full localized value use this property.
let localizedValue: String

/**
Tries to parse passed `str` parameter and created `Expression` from it.
If passed string contains expression that is supported and inside logic
compute that this string is some supported pattern an `Expression` object
will be returned.

:param: str string that may or may not contain expression pattern
:returns: `Expression` object or nil if pattern is not supported.
*/
class func expressionFromString(str: String) -> Expression? {
if let pattern = parseExpressionPattern(str) {
return Expression(pattern: pattern)
}
return nil
}
/// Array of length variations
let lengthVariations: [LengthVariation]

/**
Initializer that takes expression pattern. It may fail when expression
type of passed expression is not supported.

:param: pattern pattern of expression
:returns: `Expression` object or nil when pattern is not supported.
*/
init?(pattern: ExpressionPattern) {
// pattern is assigned even if init fails because of Swift/compiler bug.
/// Expression matcher that is used in validation
private var expressionMatcher: ExpressionMatcher? = nil

// Returns expression object
init(pattern: String, localizedValue: String, lengthVariations: [LengthVariation] = [LengthVariation]()) {
self.pattern = pattern

if let type = Expression.getExpressionType(pattern) {
self.type = type

// build correct expression matcher
buildMatcher()
if matcher == nil {
println("Cannot create expression because expression pattern cannot be parsed: \(pattern)")
return nil
self.localizedValue = localizedValue
self.lengthVariations = lengthVariations

// Create expression matcher
if let type = getExpressionType(pattern) {
switch (type as ExpressionPatternType) {
case .Inequality:
expressionMatcher = InequalityExpressionParser(pattern).parse()

case .InequalityExtended:
expressionMatcher = InequalityExtendedExpressionParser(pattern).parse()

case .Regex:
expressionMatcher = RegexExpressionParser(pattern).parse()
}
} else {
println("Cannot create expression with pattern: \(pattern).")
return nil
}
}

/**
Method that validates passed string.

:param: value value that should be matched
:returns: `true` if value match expression, otherwise `false`.
*/
func validate(value: String) -> Bool {
return matcher.validate(value)
}


// MARK: Private methods

/**
Method used to create `ExpressionMatcher` instance that match expression
pattern of this `Expression` object.
*/
private func buildMatcher() {
switch (type as ExpressionPatternType) {
case .Inequality:
matcher = InequalityExpressionParser(pattern).parse()

case .InequalityExtended:
matcher = InequalityExtendedExpressionParser(pattern).parse()

case .Regex:
matcher = RegexExpressionParser(pattern).parse()
if let matcher = expressionMatcher {
return matcher.validate(value)
} else {
return pattern == value
}
}

/**
Method used to get `ExpressionPatternType` of passed `ExpressionPattern`.
Method used to get `ExpressionPatternType` of passed `ExpressionPattern`.

:param: pattern expression pattern that will be checked.
:returns: `ExpressionPatternType` if pattern is supported, otherwise nil.
*/
private class func getExpressionType(pattern: ExpressionPattern) -> ExpressionPatternType? {
private func getExpressionType(pattern: ExpressionPattern) -> ExpressionPatternType? {
if let result = Regex.firstMatchInString(pattern, pattern: InternalPattern.ExpressionPatternType.rawValue) {
return ExpressionPatternType(rawValue: result)
}
Expand Down
9 changes: 0 additions & 9 deletions Swifternalization/ExpressionType.swift

This file was deleted.

33 changes: 0 additions & 33 deletions Swifternalization/KeyValueType.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Swifternalization/LengthVariation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
/**
Length variation representation.
*/
struct LengthVariation: LengthVariationType {
struct LengthVariation {
/// Length - width of a screen.
let length: Int

Expand Down
12 changes: 0 additions & 12 deletions Swifternalization/LengthVariationType.swift

This file was deleted.

20 changes: 10 additions & 10 deletions Swifternalization/LoadedTranslationsProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class LoadedTranslationsProcessor {
expressions as well as built-in ones. Translations are processed in shared
expressions processor.
*/
class func processTranslations(baseTranslations: [LoadedTranslation], preferedLanguageTranslations: [LoadedTranslation], sharedExpressions: [SharedExpression]) -> [TranslationType] {
class func processTranslations(baseTranslations: [LoadedTranslation], preferedLanguageTranslations: [LoadedTranslation], sharedExpressions: [SharedExpression]) -> [Translation] {

// Find those base translations that are not contained in prefered
// language translations.
Expand All @@ -49,28 +49,28 @@ class LoadedTranslationsProcessor {
case .Simple:
// Simple translation with key and value.
let value = $0.content[$0.key] as! String
return TranslationWithExpressions(key: $0.key, expressions: [SimpleExpression(pattern: $0.key, localizedValue: value)])
return Translation(key: $0.key, expressions: [Expression(pattern: $0.key, localizedValue: value)])

case .WithExpressions:
// Translation that contains expression.
// Every time when new expressions is about to create,
// the shared expressions are filtered to get expression that
// matches key and if there is a key it is replaced with real
// expression pattern.
var expressions = [ExpressionType]()
var expressions = [Expression]()
for (key, value) in $0.content as! Dictionary<String, String> {
let pattern = sharedExpressions.filter({$0.identifier == key}).first?.pattern ?? key
expressions.append(SimpleExpression(pattern: pattern, localizedValue: value))
expressions.append(Expression(pattern: pattern, localizedValue: value))
}
return TranslationWithExpressions(key: $0.key, expressions: expressions)
return Translation(key: $0.key, expressions: expressions)

case .WithLengthVariations:
// Translation contains length expressions like @100, @200, etc.
var lengthVariations = [LengthVariation]()
for (key, value) in $0.content as! Dictionary<String, String> {
lengthVariations.append(LengthVariation(length: self.parseNumberFromLengthVariation(key), value: value))
}
return TranslationWithExpressions(key: $0.key, expressions: [SimpleExpression(pattern: $0.key, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)])
return Translation(key: $0.key, expressions: [Expression(pattern: $0.key, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)])

case .WithExpressionsAndLengthVariations:
// The most advanced translation type. It contains expressions
Expand All @@ -79,20 +79,20 @@ class LoadedTranslationsProcessor {
// and .WithLengthVariations cases. key is filtered in shared
// expressions to get one of shared expressions and then method
// builds array of variations.
var expressions = [ExpressionType]()
var expressions = [Expression]()
for (key, value) in $0.content {
let pattern = sharedExpressions.filter({$0.identifier == key}).first?.pattern ?? key
if value is Dictionary<String, String> {
var lengthVariations = [LengthVariation]()
for (lvKey, lvValue) in value as! Dictionary<String, String> {
lengthVariations.append(LengthVariation(length: self.parseNumberFromLengthVariation(lvKey), value: lvValue))
}
expressions.append(SimpleExpression(pattern: pattern, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations))
expressions.append(Expression(pattern: pattern, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations))
} else if value is String {
expressions.append(SimpleExpression(pattern:pattern, localizedValue: value as! String))
expressions.append(Expression(pattern:pattern, localizedValue: value as! String))
}
}
return TranslationWithExpressions(key: $0.key, expressions: expressions)
return Translation(key: $0.key, expressions: expressions)
}
})
}
Expand Down
Loading

0 comments on commit 9b24d42

Please sign in to comment.