From dafcf2ddf4d1d2f9452f73227d20107ae673a993 Mon Sep 17 00:00:00 2001 From: Adrian Bobrowski Date: Wed, 6 May 2020 21:43:06 +0200 Subject: [PATCH 1/3] Add support for pseudolanguages defined in Schemes options --- Example/Example.xcodeproj/project.pbxproj | 4 +- .../xcschemes/Example iOS.xcscheme | 8 +- L10n_swift.xcodeproj/project.pbxproj | 68 +++++++++++++ .../xcshareddata/xcschemes/L10n iOS.xcscheme | 26 +++-- Source/Core/Extensions/L10n+static.swift | 2 +- Source/Core/L10n.swift | 53 +++++++---- .../Core/LocalizedStringsConfiguration.swift | 95 +++++++++++++++++++ Source/Core/Plural/Plural.swift | 25 +++-- Source/Core/Plural/PluralArg.swift | 1 + .../TextDecorator/AccentedTextDecorator.swift | 32 +++++++ .../TextDecorator/BoundedTextDecorator.swift | 14 +++ .../DoubleLengthTextDecorator.swift | 14 +++ .../RightToLeftTextDecorator.swift | 14 +++ Source/Core/TextDecorator/TextDecorator.swift | 12 +++ Source/Extensions/String+Localizable.swift | 77 ++++++++++++++- 15 files changed, 392 insertions(+), 53 deletions(-) create mode 100644 Source/Core/LocalizedStringsConfiguration.swift create mode 100644 Source/Core/TextDecorator/AccentedTextDecorator.swift create mode 100644 Source/Core/TextDecorator/BoundedTextDecorator.swift create mode 100644 Source/Core/TextDecorator/DoubleLengthTextDecorator.swift create mode 100644 Source/Core/TextDecorator/RightToLeftTextDecorator.swift create mode 100644 Source/Core/TextDecorator/TextDecorator.swift diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index b43fbc5..fb5f3f4 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -565,7 +565,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; @@ -627,7 +627,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; diff --git a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example iOS.xcscheme b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example iOS.xcscheme index 878de27..a681e4a 100644 --- a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example iOS.xcscheme +++ b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example iOS.xcscheme @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + - - + codeCoverageEnabled = "YES"> + + + + @@ -46,17 +55,6 @@ - - - - - - - - String { - guard let text = self.resource(named: resource)[key, fittingWidth] else { + let text: String + if self.configuration.isNonLocalized { + text = key + } else if let value = self.resource(named: resource)[key, fittingWidth] { + text = value + } else { self.logger?.info("L10n - Key \(key.debugDescription) does not exist for \(self.language.debugDescription).") - return key + text = key } - return text + return self.configuration.decorate(text: text) } /** @@ -162,20 +174,27 @@ open class L10n { - returns: A localized plural version of the string designated by `key`. This method returns `key` when `key` not found. */ open func plural(for key: String, resource: String? = nil, fittingWidth: Int? = nil, args: [CVarArg]) -> String { - let args = args.map { arg -> (CVarArg, [Plural]) in - if let pluralArg = arg as? PluralArg { - return (pluralArg.convertedArg, Plural.variants(for: pluralArg.value, with: self.locale)) + let text: String + if self.configuration.isNonLocalized { + text = key + } else { + let args = args.map { arg -> (CVarArg, [Plural]) in + if let pluralArg = arg as? PluralArg { + return (pluralArg.convertedArg, Plural.variants(for: pluralArg.value, with: self.locale)) + } + if let number = arg as? NSNumber { + return (arg, Plural.variants(for: number, with: self.locale)) + } + return (arg, []) } - if let number = arg as? NSNumber { - return (arg, Plural.variants(for: number, with: self.locale)) + if let format = self.resource(named: resource)[key, args.map { $0.1 }, fittingWidth] { + text = self.string(format: format, args: args.map { $0.0 }) + } else { + self.logger?.info("L10n - Key \(key.debugDescription) does not support plural for \(self.language.debugDescription).") + text = key } - return (arg, []) - } - guard let format = self.resource(named: resource)[key, args.map { $0.1 }, fittingWidth] else { - self.logger?.info("L10n - Key \(key.debugDescription) does not support plural for \(self.language.debugDescription).") - return key } - return self.string(format: format, args: args.map { $0.0 }) + return self.configuration.decorate(text: text) } /** diff --git a/Source/Core/LocalizedStringsConfiguration.swift b/Source/Core/LocalizedStringsConfiguration.swift new file mode 100644 index 0000000..d312744 --- /dev/null +++ b/Source/Core/LocalizedStringsConfiguration.swift @@ -0,0 +1,95 @@ +// +// LocalizedStringsConfiguration.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 05/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +import Foundation + +/// Struct LocalizedStringsConfiguration used to modification of output. +public struct LocalizedStringsConfiguration: TextDecorator { + + /// A shared instance of `L10n`. + public static let shared: LocalizedStringsConfiguration = .init(userDefaults: .standard) + + /// A Boolean value indicating whether a text shouldn't be localized. If `true`, the localization key will be returned as text. + public var isNonLocalized: Bool + + /// A Boolean value indicating whether a text should be doubled. + public var isDoubleLength: Bool { + didSet { + self.update() + } + } + + /// A Boolean value indicating whether a text should be accented. + public var isAccented: Bool { + didSet { + self.update() + } + } + + /// A Boolean value indicating whether a text should be bounded. + public var isBounded: Bool { + didSet { + self.update() + } + } + + /// A Boolean value indicating whether a text should be reversed. + public var isForcedRightToLeft: Bool { + didSet { + self.update() + } + } + + private var decorators: [TextDecorator] = [] + + func decorate(text: String) -> String { + return self.decorators.reduce(into: text) { $0 = $1.decorate(text: $0) } + } + + public init( + isNonLocalized: Bool = false, + isDoubleLength: Bool = false, + isAccented: Bool = false, + isBounded: Bool = false, + isForcedRightToLeft: Bool = false + ) { + self.isNonLocalized = isNonLocalized + self.isDoubleLength = isDoubleLength + self.isAccented = isAccented + self.isBounded = isBounded + self.isForcedRightToLeft = isForcedRightToLeft + self.update() + } + + public init(userDefaults: UserDefaults) { + self.init( + isNonLocalized: userDefaults.bool(forKey: "NSShowNonLocalizedStrings"), + isDoubleLength: userDefaults.bool(forKey: "NSDoubleLocalizedStrings"), + isAccented: userDefaults.bool(forKey: "NSAccentuateLocalizedStrings"), + isBounded: userDefaults.bool(forKey: "NSSurroundLocalizedStrings"), + isForcedRightToLeft: userDefaults.bool(forKey: "NSForceRightToLeftLocalizedStrings") + ) + } + + private mutating func update() { + var decorators: [TextDecorator] = [] + if self.isForcedRightToLeft { + decorators.append(RightToLeftTextDecorator()) + } + if self.isAccented { + decorators.append(AccentedTextDecorator()) + } + if self.isDoubleLength { + decorators.append(DoubleLengthTextDecorator()) + } + if self.isBounded { + decorators.append(BoundedTextDecorator()) + } + self.decorators = decorators + } +} diff --git a/Source/Core/Plural/Plural.swift b/Source/Core/Plural/Plural.swift index 3bfdf35..ad34dff 100644 --- a/Source/Core/Plural/Plural.swift +++ b/Source/Core/Plural/Plural.swift @@ -46,13 +46,22 @@ extension Plural { let `extension` = "stringsdict" var bundle = Bundle(for: L10n.self) - if bundle.url(forResource: table, withExtension: `extension`) == nil, - case let subdirectory = "spmResources", - bundle.url(forResource: table, withExtension: `extension`, subdirectory: subdirectory) == nil - { - // FIXME: This is temporary solution for Swift Package Manager. - // See also: https://github.com/Decybel07/L10n-swift/issues/21 - + if bundle.url(forResource: table, withExtension: `extension`) == nil { + self.createFileIfNeeded(table: table, extension: `extension`, bundle: &bundle) + } + + return bundle.localizedString(forKey: "integer", value: "other", table: table) + } + + /** + This is temporary solution for Swift Package Manager. + + - SeeAlso: + [Issue #21](https://github.com/Decybel07/L10n-swift/issues/21) + */ + private static func createFileIfNeeded(table: String, `extension`: String, bundle: inout Bundle) { + let subdirectory = "spmResources" + if bundle.url(forResource: table, withExtension: `extension`, subdirectory: subdirectory) == nil { let baseUrl = bundle.bundleURL.appendingPathComponent(subdirectory) let url = baseUrl.appendingPathComponent(table).appendingPathExtension(`extension`) let fileContent = """ @@ -96,7 +105,5 @@ extension Plural { L10n.shared.logger?.log("Can't create \(url): \(error.localizedDescription)") } } - - return bundle.localizedString(forKey: "integer", value: "other", table: table) } } diff --git a/Source/Core/Plural/PluralArg.swift b/Source/Core/Plural/PluralArg.swift index 18de9de..5b18013 100644 --- a/Source/Core/Plural/PluralArg.swift +++ b/Source/Core/Plural/PluralArg.swift @@ -8,6 +8,7 @@ import Foundation +/// Protocol PluralArg. public protocol PluralArg: CVarArg { var arg: CVarArg { get } diff --git a/Source/Core/TextDecorator/AccentedTextDecorator.swift b/Source/Core/TextDecorator/AccentedTextDecorator.swift new file mode 100644 index 0000000..59fc944 --- /dev/null +++ b/Source/Core/TextDecorator/AccentedTextDecorator.swift @@ -0,0 +1,32 @@ +// +// AccentedTextDecorator.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 05/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +struct AccentedTextDecorator: TextDecorator { + + private static let up = "\u{0300}\u{0301}\u{0302}\u{0303}\u{0304}\u{0306}\u{0307}\u{0308}\u{030A}\u{030B}\u{030C}\u{030D}\u{030E}\u{030F}\u{0310}\u{0311}\u{0312}\u{0313}\u{0314}\u{0342}\u{0343}\u{034A}" + private static let down = "\u{0316}\u{0317}\u{031c}\u{0324}\u{0325}\u{0326}\u{0329}\u{032b}\u{032c}\u{032d}\u{032e}\u{032f}\u{0330}\u{0331}" + + func decorate(text: String) -> String { + return text.map(self.decorate(char:)).joined() + } + + private func decorate(char: Character) -> String { + let base = String(char) + guard char.isLetter else { + return base + } + let hash = abs(char.hashValue) + return base + + self.scalar(Self.up.unicodeScalars, for: hash) + + self.scalar(Self.down.unicodeScalars, for: hash) + } + + private func scalar(_ unicodeScalars: String.UnicodeScalarView, for hash: Int) -> String { + return String(unicodeScalars[unicodeScalars.index(unicodeScalars.startIndex, offsetBy: hash % unicodeScalars.count)]) + } +} diff --git a/Source/Core/TextDecorator/BoundedTextDecorator.swift b/Source/Core/TextDecorator/BoundedTextDecorator.swift new file mode 100644 index 0000000..b5d1241 --- /dev/null +++ b/Source/Core/TextDecorator/BoundedTextDecorator.swift @@ -0,0 +1,14 @@ +// +// BoundedTextDecorator.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 06/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +struct BoundedTextDecorator: TextDecorator { + + func decorate(text: String) -> String { + return "[# \(text) #]" + } +} diff --git a/Source/Core/TextDecorator/DoubleLengthTextDecorator.swift b/Source/Core/TextDecorator/DoubleLengthTextDecorator.swift new file mode 100644 index 0000000..8058424 --- /dev/null +++ b/Source/Core/TextDecorator/DoubleLengthTextDecorator.swift @@ -0,0 +1,14 @@ +// +// DoubleLengthTextDecorator.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 05/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +struct DoubleLengthTextDecorator: TextDecorator { + + func decorate(text: String) -> String { + return "\(text) \(text)" + } +} diff --git a/Source/Core/TextDecorator/RightToLeftTextDecorator.swift b/Source/Core/TextDecorator/RightToLeftTextDecorator.swift new file mode 100644 index 0000000..78c1ff9 --- /dev/null +++ b/Source/Core/TextDecorator/RightToLeftTextDecorator.swift @@ -0,0 +1,14 @@ +// +// RightToLeftTextDecorator.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 05/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +struct RightToLeftTextDecorator: TextDecorator { + + func decorate(text: String) -> String { + return String(text.reversed()) + } +} diff --git a/Source/Core/TextDecorator/TextDecorator.swift b/Source/Core/TextDecorator/TextDecorator.swift new file mode 100644 index 0000000..2ca1e6c --- /dev/null +++ b/Source/Core/TextDecorator/TextDecorator.swift @@ -0,0 +1,12 @@ +// +// TextDecorator.swift +// L10n_swift +// +// Created by Adrian Bobrowski on 05/05/2020. +// Copyright © 2020 Adrian Bobrowski (Decybel07), adrian071993@gmail.com. All rights reserved. +// + +protocol TextDecorator { + + func decorate(text: String) -> String +} diff --git a/Source/Extensions/String+Localizable.swift b/Source/Extensions/String+Localizable.swift index c82a1e2..bd1ff08 100644 --- a/Source/Extensions/String+Localizable.swift +++ b/Source/Extensions/String+Localizable.swift @@ -23,7 +23,6 @@ extension String: Localizable { Returns a localized version of the string designated by the `self` and residing in `resource`. - parameter instance: The instance of `L10n` used for localization. - - parameter resource: The receiver’s string resource to search. If resource is nil or is an empty string, the method attempts to use the resource in **Localizable** files. - parameter fittingWidth: The desired width of the string variation. - returns: A localized version of the string designated by `self` or `self` if not found. @@ -45,6 +44,42 @@ extension String: Localizable { return instance.string(for: self, resource: resource, fittingWidth: fittingWidth) } + /** + Returns a localized version of the string designated by the `self`, residing in `resource` and filled with the values of the arguments. + + - parameter args: The values used to fill. + + - returns: A localized version of the string designated by `self` or `self` if not found. + */ + public func l10n(_ args: CVarArg...) -> String { + return self.l10n(.shared, resource: nil, fittingWidth: nil, args: args) + } + + /** + Returns a localized version of the string designated by the `self`, residing in `resource` and filled with the values of the arguments. + + - parameter instance: The instance of `L10n` used for localization. + - parameter args: The values used to fill. + + - returns: A localized version of the string designated by `self` or `self` if not found. + */ + public func l10n(_ instance: L10n = .shared, _ args: CVarArg...) -> String { + return self.l10n(instance, resource: nil, fittingWidth: nil, args: args) + } + + /** + Returns a localized version of the string designated by the `self`, residing in `resource` and filled with the values of the arguments. + + - parameter instance: The instance of `L10n` used for localization. + - parameter resource: The receiver’s string resource to search. If resource is nil or is an empty string, the method attempts to use the resource in **Localizable** files. + - parameter args: The values used to fill. + + - returns: A localized version of the string designated by `self` or `self` if not found. + */ + public func l10n(_ instance: L10n = .shared, resource: String, _ args: CVarArg...) -> String { + return self.l10n(instance, resource: resource, fittingWidth: nil, args: args) + } + /** Returns a localized version of the string designated by the `self`, residing in `resource` and filled with the values of the arguments. @@ -55,7 +90,7 @@ extension String: Localizable { - returns: A localized version of the string designated by `self` or `self` if not found. */ - public func l10n(_ instance: L10n = .shared, resource: String? = nil, fittingWidth: Int? = nil, _ args: CVarArg...) -> String { + public func l10n(_ instance: L10n = .shared, resource: String? = nil, fittingWidth: Int, _ args: CVarArg...) -> String { return self.l10n(instance, resource: resource, fittingWidth: fittingWidth, args: args) } @@ -74,6 +109,42 @@ extension String: Localizable { return instance.string(format: localizedFormat, args: args) } + /** + Returns a localized plural version of the string designated by the specified `slef` and `args` and residing in `resource`. + + - parameter args: The values for which the appropriate plural form is selected. If you want to modify the argument to be displayed, use `PluralArg` (eg. `NumericPluralArg`). + + - returns: A localized plural version of the string designated by `key`. This method returns `key` when `key` not found. + */ + public func l10nPlural(_ args: CVarArg...) -> String { + return self.l10nPlural(.shared, resource: nil, fittingWidth: nil, args: args) + } + + /** + Returns a localized plural version of the string designated by the specified `slef` and `args` and residing in `resource`. + + - parameter instance: The instance of `L10n` used for localization. + - parameter args: The values for which the appropriate plural form is selected. If you want to modify the argument to be displayed, use `PluralArg` (eg. `NumericPluralArg`). + + - returns: A localized plural version of the string designated by `key`. This method returns `key` when `key` not found. + */ + public func l10nPlural(_ instance: L10n, _ args: CVarArg...) -> String { + return self.l10nPlural(instance, resource: nil, fittingWidth: nil, args: args) + } + + /** + Returns a localized plural version of the string designated by the specified `slef` and `args` and residing in `resource`. + + - parameter instance: The instance of `L10n` used for localization. + - parameter resource: The receiver’s string resource to search. If resource is nil or is an empty string, the method attempts to use the resource in **Localizable** files. + - parameter args: The values for which the appropriate plural form is selected. If you want to modify the argument to be displayed, use `PluralArg` (eg. `NumericPluralArg`). + + - returns: A localized plural version of the string designated by `key`. This method returns `key` when `key` not found. + */ + public func l10nPlural(_ instance: L10n = .shared, resource: String, _ args: CVarArg...) -> String { + return self.l10nPlural(instance, resource: resource, fittingWidth: nil, args: args) + } + /** Returns a localized plural version of the string designated by the specified `slef` and `args` and residing in `resource`. @@ -84,7 +155,7 @@ extension String: Localizable { - returns: A localized plural version of the string designated by `key`. This method returns `key` when `key` not found. */ - public func l10nPlural(_ instance: L10n = .shared, resource: String? = nil, fittingWidth: Int? = nil, _ args: CVarArg...) -> String { + public func l10nPlural(_ instance: L10n = .shared, resource: String? = nil, fittingWidth: Int, _ args: CVarArg...) -> String { return self.l10nPlural(instance, resource: resource, fittingWidth: fittingWidth, args: args) } From a5d187fe67b13fa4cd33b817eea63aa4d3ae2d0b Mon Sep 17 00:00:00 2001 From: Adrian Bobrowski Date: Wed, 6 May 2020 21:46:38 +0200 Subject: [PATCH 2/3] typo --- Source/Core/L10n.swift | 1 - Source/Core/TextDecorator/AccentedTextDecorator.swift | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Core/L10n.swift b/Source/Core/L10n.swift index aae4b31..8b5e5e0 100644 --- a/Source/Core/L10n.swift +++ b/Source/Core/L10n.swift @@ -54,7 +54,6 @@ open class L10n { return self.languageCode } set { - newValue.isEmpty if newValue == "Base", let developmentLanguage = self.coreBundle.developmentLocalization { self.language = developmentLanguage return diff --git a/Source/Core/TextDecorator/AccentedTextDecorator.swift b/Source/Core/TextDecorator/AccentedTextDecorator.swift index 59fc944..7a37450 100644 --- a/Source/Core/TextDecorator/AccentedTextDecorator.swift +++ b/Source/Core/TextDecorator/AccentedTextDecorator.swift @@ -22,8 +22,8 @@ struct AccentedTextDecorator: TextDecorator { } let hash = abs(char.hashValue) return base - + self.scalar(Self.up.unicodeScalars, for: hash) - + self.scalar(Self.down.unicodeScalars, for: hash) + + self.scalar(AccentedTextDecorator.up.unicodeScalars, for: hash) + + self.scalar(AccentedTextDecorator.down.unicodeScalars, for: hash) } private func scalar(_ unicodeScalars: String.UnicodeScalarView, for hash: Int) -> String { From a4e456396e4365157b0b76ff56c18249f129a15f Mon Sep 17 00:00:00 2001 From: Adrian Bobrowski Date: Thu, 7 May 2020 15:24:49 +0200 Subject: [PATCH 3/3] Prepare to release --- CHANGELOG.md | 3 +++ L10n-swift.podspec | 3 ++- README.md | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 301cd11..5a1b677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # Change Log --- +## [5.7.0](https://github.com/Decybel07/L10n-swift/tree/5.7.0) (2020-05-07) +* Support for pseudo-languages: `NonLocalized`, `DoubleLength`, `Accented`, `Bounded`, `ForcedRightToLeft`. + ## [5.6.1](https://github.com/Decybel07/L10n-swift/tree/5.6.1) (2020-03-02) * Temporary solution for plurals when using Swift PM [#21](https://github.com/Decybel07/L10n-swift/issues/21) diff --git a/L10n-swift.podspec b/L10n-swift.podspec index 3facfa9..222b289 100644 --- a/L10n-swift.podspec +++ b/L10n-swift.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |spec| spec.name = 'L10n-swift' spec.module_name = 'L10n_swift' - spec.version = '5.6.1' + spec.version = '5.7.0' spec.summary = 'Localization of an application with ability to change language "on the fly" and support for plural forms in any language.' spec.description = <<-DESC @@ -13,6 +13,7 @@ Pod::Spec.new do |spec| * Support for formats: `*.plist`, `*.json`, `*.stringsdict`, `*.strings`. * Support for grouping localization keys. * Support for plural forms in any language with multiple arguments. + * Support for pseudo-languages: `NonLocalized`, `DoubleLength`, `Accented`, `Bounded`, `ForcedRightToLeft`. * Use .l10n() to localized any string, date and numbers. * Use more than one languages at the same time. DESC diff --git a/README.md b/README.md index 42c63e8..e68c3fc 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ L10n-swift is a simple framework that improves localization in swift app, provid - [x] Support for formats: [`*.plist`](https://github.com/Decybel07/L10n-swift/wiki/*.plist), [`*.json`](https://github.com/Decybel07/L10n-swift/wiki/*.json), [`*.stringsdict`](https://github.com/Decybel07/L10n-swift/wiki/*.stringsdict), [`*.strings`](https://github.com/Decybel07/L10n-swift/wiki/*.strings). - [x] Support for grouping localization keys. - [x] Support for [**plural**](https://github.com/Decybel07/L10n-swift/wiki/Plural) forms in any language with multiple arguments. +- [x] Support for pseudo-languages: `NonLocalized`, `DoubleLength`, `Accented`, `Bounded`, `ForcedRightToLeft`. - [x] Use `.l10n()` to localize any string, date and numbers. - [x] Use more than one language at the same time. - [x] About 25 times faster than a native solution. @@ -70,13 +71,13 @@ pod try L10n-swift ### [CocoaPods](http://cocoapods.org) ```ruby - pod 'L10n-swift', '~> 5.6' + pod 'L10n-swift', '~> 5.7' ``` ### [Carthage](https://github.com/Carthage/Carthage) ```ogdl -github "Decybel07/L10n-swift", ~> 5.6 +github "Decybel07/L10n-swift", ~> 5.7 ``` ### [Swift Package Manager](https://swift.org/package-manager/) @@ -96,7 +97,7 @@ github "Decybel07/L10n-swift", ~> 5.6 Add `.l10()` following any `String` object you want localized: ```swift - "HelloWorld".l10n() + "hello.world".l10n() ``` ### Get localized number @@ -128,7 +129,7 @@ github "Decybel07/L10n-swift", ~> 5.6 Add `.l10nPlural(CVarArg...)` following any `String` object you want translated with plurals: ```swift - "numberOfApples".l10nPlural(args: [2]) + "numberOfApples".l10nPlural(2) ``` More about plurals, you can read on [**wiki**](https://github.com/Decybel07/L10n-swift/wiki/Plural)