├── .gitignore
├── LocalizedSwift.jpg
├── Example
├── Localizable strings
│ ├── Localizable.strings
│ └── AnotherFile.strings
├── Supporting files
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── earth.imageset
│ │ │ ├── earth.jpg
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ └── LaunchScreen.storyboard
├── AppDelegate.swift
├── ViewController.swift
├── Info.plist
└── Main.storyboard
├── .swiftpm
└── xcode
│ ├── package.xcworkspace
│ └── contents.xcworkspacedata
│ └── xcuserdata
│ └── mario.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── LocalizedSwift.xcworkspace
├── xcuserdata
│ └── mario.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── LocalizedSwift.xcodeproj
├── xcuserdata
│ └── mario.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── Example.xcscheme
└── project.pbxproj
├── LocalizedSwift.podspec
├── Package.swift
├── LICENSE
├── Sources
└── Localized
│ ├── LocalizedKeyProvided.swift
│ ├── Localizable.swift
│ └── Localized.swift
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 |
--------------------------------------------------------------------------------
/LocalizedSwift.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarioIannotta/LocalizedSwift/HEAD/LocalizedSwift.jpg
--------------------------------------------------------------------------------
/Example/Localizable strings/Localizable.strings:
--------------------------------------------------------------------------------
1 | "Label.Title" = "This is localized label";
2 | "Image.Earth" = "earth";
3 |
--------------------------------------------------------------------------------
/Example/Supporting files/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Supporting files/Assets.xcassets/earth.imageset/earth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarioIannotta/LocalizedSwift/HEAD/Example/Supporting files/Assets.xcassets/earth.imageset/earth.jpg
--------------------------------------------------------------------------------
/Example/Localizable strings/AnotherFile.strings:
--------------------------------------------------------------------------------
1 | "Button.Title" = "Normal button title";
2 | "Button.Selected.Title" = "Selected button title";
3 | "Button.Highlighted.Title" = "Highlighted button title";
4 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LocalizedSwift.xcworkspace/xcuserdata/mario.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarioIannotta/LocalizedSwift/HEAD/LocalizedSwift.xcworkspace/xcuserdata/mario.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/LocalizedSwift.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LocalizedSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Supporting files/Assets.xcassets/earth.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "earth.jpg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/LocalizedSwift.xcodeproj/xcuserdata/mario.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Example.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/xcuserdata/mario.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Localized.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 1
11 |
12 | LocalizedSwift.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 0
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Localizable Demo
4 | //
5 | // Created by Mario Iannotta on 21/02/2020.
6 | // Copyright © 2020 Mario Iannotta. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/LocalizedSwift.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'LocalizedSwift'
3 | s.version = '1.0.2'
4 | s.summary = 'Localize UI Components in a simple and declarative way'
5 | s.description = <<-DESC
6 | LocalizedSwift provide a property wrapper to localize UI Components using a simple declarative qualifier.
7 | DESC
8 | s.swift_version = '5.1'
9 | s.homepage = 'https://github.com/MarioIannotta/LocalizedSwift'
10 | s.license = { :type => 'MIT', :file => 'LICENSE' }
11 | s.author = { 'MarioIannotta' => 'info@marioiannotta.com' }
12 | s.source = { :git => 'https://github.com/MarioIannotta/LocalizedSwift.git', :tag => s.version.to_s }
13 | s.social_media_url = 'https://twitter.com/MarioIannotta'
14 | s.ios.deployment_target = '10.0'
15 | s.source_files = 'Sources/**/*'
16 | end
17 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "LocalizedSwift",
8 | platforms: [
9 | .iOS(.v10), .tvOS(.v9),
10 | ],
11 | products: [
12 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
13 | .library(
14 | name: "Localized",
15 | targets: ["Localized"]),
16 | ],
17 | dependencies: [
18 | // Dependencies declare other packages that this package depends on.
19 | // .package(url: /* package url */, from: "1.0.0"),
20 | ],
21 | targets: [
22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
23 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
24 | .target(
25 | name: "Localized",
26 | dependencies: [])
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Mario Iannotta
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Example/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Localizable Demo
4 | //
5 | // Created by Mario Iannotta on 21/02/2020.
6 | // Copyright © 2020 Mario. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Localized
11 |
12 | class ViewController: UIViewController {
13 |
14 | @Localized("Image.Earth")
15 | @IBOutlet private var imageView: UIImageView!
16 |
17 | @Localized("Label.Title")
18 | @IBOutlet private var label: UILabel!
19 |
20 | @Localized(.key("Button.Title", for: .normal),
21 | .key("Button.Selected.Title", for: .selected), stringsFileName: "AnotherFile")
22 | @IBOutlet private var firstButton: UIButton!
23 |
24 | @Localized(.key(ButtonStrings.normal, for: .normal),
25 | .key(ButtonStrings.highlighted, for: .highlighted), stringsFileName: "AnotherFile")
26 | @IBOutlet private var secondButton: UIButton!
27 |
28 | @IBAction private func secondButtonDidTap() {
29 | firstButton.isSelected = !firstButton.isSelected
30 | }
31 |
32 | }
33 |
34 | enum ButtonStrings: String, LocalizedKeyProvider {
35 | case normal = "Button.Title"
36 | case highlighted = "Button.Highlighted.Title"
37 | case selected = "Button.Selected.Title"
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Localized/LocalizedKeyProvided.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LocalizedKeyProvided.swift
3 | // Localizable
4 | //
5 | // Created by Mario Iannotta on 24/02/2020.
6 | // Copyright © 2020 Mario. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | A protocol that acts as abstraction layer to provide a generic object as key provider.
13 |
14 | By default `String` already conforms the protocol and a basic implementation for enums enums with strings as raw value is provided.
15 | If you want to use the latter you'll just need to make your enum conform `LocalizedKeyProvider`.
16 |
17 | Example:
18 | ```
19 | class ViewConroller: UIViewController {
20 |
21 | @Localized(MyStrings.myLabel)
22 | @IBOutlet private var label: UILabel!
23 |
24 | }
25 |
26 | enum MyStrings: String, LocalizedKeyProvider {
27 | case myLabel = "MyStrings.MyLabel"
28 | // ...
29 | }
30 | ```
31 | */
32 | public protocol LocalizedKeyProvider {
33 |
34 | /**
35 | The localized key that will be used. By default, for strings the string itself will be used; for enums with strings as rawValue, the rawValue.
36 | */
37 | var localizedKey: String { get }
38 | }
39 |
40 | public extension LocalizedKeyProvider where Self: RawRepresentable, RawValue == String {
41 | var localizedKey: String { rawValue }
42 | }
43 |
44 | extension String: LocalizedKeyProvider {
45 | public var localizedKey: String { self }
46 | }
47 |
--------------------------------------------------------------------------------
/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Supporting files/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Supporting files/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Sources/Localized/Localizable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Localizable.swift
3 | // Localizable
4 | //
5 | // Created by Mario Iannotta on 20/02/2020.
6 | // Copyright © 2020 Mario. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A protocol that allow to localize components using the property wrapper `@Localized`.
13 | `UILabel`, `UIButton` and `UITextField` already conform this protocol.
14 | */
15 | public protocol Localizable {
16 |
17 | /**
18 | Set the provided localized string for a provided state.
19 | - Parameters:
20 | - string: the localized string.
21 | - state: the state for which the string should be set.
22 | */
23 | func setLocalizedString(_ string: String, for state: UIControl.State)
24 |
25 | }
26 |
27 | /**
28 | A model to associate a key provider to a `UIControl.State`.
29 | */
30 | public struct LocalizedConfiguration {
31 | let state: UIControl.State
32 | let keyProvider: KeyProvider
33 |
34 | private init(state: UIControl.State, keyProvider: KeyProvider) {
35 | self.state = state
36 | self.keyProvider = keyProvider
37 | }
38 |
39 | /**
40 | A syntactic sugar shortcut to create a `LocalizedConfiguration`.
41 | - Parameters:
42 | - keyProvider: The localized key provider.
43 | - state: The associated state.
44 | */
45 | public static func key(_ keyProvider: KeyProvider, for state: UIControl.State) -> LocalizedConfiguration {
46 | LocalizedConfiguration(state: state, keyProvider: keyProvider)
47 | }
48 | }
49 |
50 | extension UIButton: Localizable {
51 |
52 | var localizedState: UIControl.State {
53 | state
54 | }
55 |
56 | public func setLocalizedString(_ string: String, for state: UIControl.State) {
57 | setTitle(string, for: state)
58 | }
59 | }
60 |
61 | extension UILabel: Localizable {
62 |
63 | public func setLocalizedString(_ string: String, for state: UIControl.State) {
64 | text = string
65 | }
66 | }
67 |
68 | extension UITextField: Localizable {
69 |
70 | public func setLocalizedString(_ string: String, for state: UIControl.State) {
71 | placeholder = string
72 | }
73 | }
74 |
75 | extension UIImageView: Localizable {
76 |
77 | public func setLocalizedString(_ string: String, for state: UIControl.State) {
78 | image = UIImage(named: string)
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Sources/Localized/Localized.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Localizable.swift
3 | // Localizable
4 | //
5 | // Created by Mario Iannotta on 20/02/2020.
6 | // Copyright © 2020 Mario. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | A property wrapper to localize UI Components in a simple and declarative way.
13 | It is possible to localize custom components making the component conform the protocol `Localizable`.
14 | */
15 | @propertyWrapper
16 | public struct Localized {
17 |
18 | private let configurations: [LocalizedConfiguration]
19 | private let bundle: Bundle
20 | private let stringsFileName: String?
21 |
22 | public var wrappedValue: Item? {
23 | didSet {
24 | guard
25 | let wrappedValue = wrappedValue
26 | else { return }
27 | configurations.forEach {
28 | let string = NSLocalizedString($0.keyProvider.localizedKey, tableName: stringsFileName, bundle: bundle, comment: "")
29 | wrappedValue.setLocalizedString(string, for: $0.state)
30 | }
31 | }
32 | }
33 |
34 | /**
35 | Create a new localized component.
36 | - Parameters:
37 | - configurations: A list of configurations where it is possible to declare a keyProvider for each `UIControl.State`.
38 | - stringsFileName: The `.strings` file name. If none is provided the keyProvider will be fetched from `Localizable.string`.
39 | - bundle: The bundle that include the localized `.strings` file. The default is `.main`.
40 |
41 | Example:
42 | ```
43 | @Localized(.key("Button.Title", for: .normal),
44 | .key("Button.Highlighted.Title", for: .highlighted))
45 | @IBOutlet private var secondButton: UIButton!
46 | ```
47 | */
48 | public init(_ configurations: LocalizedConfiguration..., stringsFileName: String? = nil, bundle: Bundle = .main) {
49 | self.configurations = configurations
50 | self.bundle = bundle
51 | self.stringsFileName = stringsFileName
52 | }
53 |
54 | /**
55 | Create a new localized component.
56 | - Parameters:
57 | - keyProvider: The key provider of the localized strings.
58 | - stringsFileName: The `.strings` file name. If none is provided the key will be fetched from `Localizable.string`.
59 | - bundle: The bundle that include the localized `.strings` file. The default is `.main`.
60 |
61 | Example:
62 | ```
63 | @Localized("Label.Title", stringsFileName: "AStringsFile", bundle: .aBundle)
64 | @IBOutlet private var label: UILabel!
65 | ```
66 | */
67 | public init(_ key: KeyProvider, stringsFileName: String? = nil, bundle: Bundle = .main) {
68 | self.init(.key(key, for: .normal), stringsFileName: stringsFileName, bundle: bundle)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Installation
6 | [](https://cocoapods.org/pods/LocalizedSwift)
7 | [](https://cocoapods.org/pods/LocalizedSwift)
8 | [](https://cocoapods.org/pods/LocalizedSwift)
9 |
10 | ### Pods
11 | > pod 'LocalizedSwift'
12 |
13 | ## Swift package manager
14 | > From Xcode, select File → Swift Packages → Add Package Dependency → Select your project → Search **LocalizedSwift**
15 |
16 | # Usage
17 |
18 | It is possible to localize a class that conforms `Localizable` adding `@Localized("YouKey")` before the component declaration.
19 | `UILabel`, `UIButton`, `UITextField` and `UIImageView` already conform `Localizable`.
20 | ```swift
21 | // In the following example the string for the key "Label.Title" will be searched in the file "Localizable.strings".
22 | @Localized("Label.Title")
23 | @IBOutlet private var label: UILabel!
24 | ```
25 |
26 | If the strings are defined in a file different from `Localizable.strings` set the parameter `stringsFileName` with the name of the file.
27 | ```swift
28 | // In the following example the string for the key "Label.Title" will be searched in the file "AFile.strings".
29 | @Localized("Label.Title", stringsFileName: "AFile")
30 | @IBOutlet private var label: UILabel!
31 | ```
32 |
33 | If the `.strings` file is in a bundle other than `.main` set the parameter `bundle` with the bundle where the file is embedded.
34 | ```swift
35 | // In the following example the string for the key "Label.Title" will be searched in the file "AFile.strings" in the bundle `.anotherBundle`.
36 | @Localized("Label.Title", stringsFileName: "AFile", bundle: .anotherBundle)
37 | @IBOutlet private var label: UILabel!
38 | ```
39 |
40 | ### Set strings for state
41 |
42 | It is possible to set different localized strings for different `UIControl.State` using the declaration `@Localized(.key(, for:), .key(, for:) ..., stringsFileName:, bundle:)`.
43 |
44 | The method `.key(:, for: )` is a factory method to instantiate the object that associate a key to a state `LocalizedConfiguration`.
45 | ```swift
46 | // In the following example the string for the key "Button.Title" will be set for the normal state and the string for the key "Button.Highlighted.Title" will be set for the highlighted state.
47 | @Localized(.key("Button.Title", for: .normal),
48 | .key("Button.Highlighted.Title", for: .highlighted))
49 | @IBOutlet private var button: UIButton!
50 | ```
51 |
52 | It is possible to set `stringsFileName` and `bundle` just like in the examples above.
53 |
54 | # Info
55 | Made with ❤️ and ☕️ by [@MarioIannotta](http://www.twitter.com/marioiannotta)
56 |
--------------------------------------------------------------------------------
/LocalizedSwift.xcodeproj/xcshareddata/xcschemes/Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Example/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
40 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/LocalizedSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | AC2CA9352400734700F0F6E1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC2CA92B2400734600F0F6E1 /* LaunchScreen.storyboard */; };
11 | AC2CA9362400734700F0F6E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC2CA92C2400734600F0F6E1 /* Assets.xcassets */; };
12 | AC2CA9382400734700F0F6E1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC2CA92E2400734600F0F6E1 /* AppDelegate.swift */; };
13 | AC2CA93A2400734700F0F6E1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC2CA9302400734600F0F6E1 /* Main.storyboard */; };
14 | AC2CA93B2400734700F0F6E1 /* AnotherFile.strings in Resources */ = {isa = PBXBuildFile; fileRef = AC2CA9322400734700F0F6E1 /* AnotherFile.strings */; };
15 | AC2CA93C2400734700F0F6E1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AC2CA9332400734700F0F6E1 /* Localizable.strings */; };
16 | AC2CA93D2400734700F0F6E1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC2CA9342400734700F0F6E1 /* ViewController.swift */; };
17 | AC2CA9412400744200F0F6E1 /* Localized in Frameworks */ = {isa = PBXBuildFile; productRef = AC2CA9402400744200F0F6E1 /* Localized */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | AC2CA9132400731E00F0F6E1 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | AC2CA92B2400734600F0F6E1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
23 | AC2CA92C2400734600F0F6E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
24 | AC2CA92D2400734600F0F6E1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
25 | AC2CA92E2400734600F0F6E1 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
26 | AC2CA9302400734600F0F6E1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
27 | AC2CA9322400734700F0F6E1 /* AnotherFile.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = AnotherFile.strings; sourceTree = ""; };
28 | AC2CA9332400734700F0F6E1 /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; };
29 | AC2CA9342400734700F0F6E1 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
30 | AC2CA93E240073FF00F0F6E1 /* */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ""; sourceTree = ""; };
31 | /* End PBXFileReference section */
32 |
33 | /* Begin PBXFrameworksBuildPhase section */
34 | AC2CA9102400731E00F0F6E1 /* Frameworks */ = {
35 | isa = PBXFrameworksBuildPhase;
36 | buildActionMask = 2147483647;
37 | files = (
38 | AC2CA9412400744200F0F6E1 /* Localized in Frameworks */,
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | AC2CA90A2400731E00F0F6E1 = {
46 | isa = PBXGroup;
47 | children = (
48 | AC2CA93E240073FF00F0F6E1 /* */,
49 | AC2CA9152400731E00F0F6E1 /* Example */,
50 | AC2CA9142400731E00F0F6E1 /* Products */,
51 | AC2CA93F2400744200F0F6E1 /* Frameworks */,
52 | );
53 | sourceTree = "";
54 | };
55 | AC2CA9142400731E00F0F6E1 /* Products */ = {
56 | isa = PBXGroup;
57 | children = (
58 | AC2CA9132400731E00F0F6E1 /* Example.app */,
59 | );
60 | name = Products;
61 | sourceTree = "";
62 | };
63 | AC2CA9152400731E00F0F6E1 /* Example */ = {
64 | isa = PBXGroup;
65 | children = (
66 | AC2CA9302400734600F0F6E1 /* Main.storyboard */,
67 | AC2CA92E2400734600F0F6E1 /* AppDelegate.swift */,
68 | AC2CA9342400734700F0F6E1 /* ViewController.swift */,
69 | AC2CA9312400734600F0F6E1 /* Localizable strings */,
70 | AC2CA92A2400734600F0F6E1 /* Supporting files */,
71 | );
72 | path = Example;
73 | sourceTree = "";
74 | };
75 | AC2CA92A2400734600F0F6E1 /* Supporting files */ = {
76 | isa = PBXGroup;
77 | children = (
78 | AC2CA92B2400734600F0F6E1 /* LaunchScreen.storyboard */,
79 | AC2CA92C2400734600F0F6E1 /* Assets.xcassets */,
80 | AC2CA92D2400734600F0F6E1 /* Info.plist */,
81 | );
82 | path = "Supporting files";
83 | sourceTree = "";
84 | };
85 | AC2CA9312400734600F0F6E1 /* Localizable strings */ = {
86 | isa = PBXGroup;
87 | children = (
88 | AC2CA9322400734700F0F6E1 /* AnotherFile.strings */,
89 | AC2CA9332400734700F0F6E1 /* Localizable.strings */,
90 | );
91 | path = "Localizable strings";
92 | sourceTree = "";
93 | };
94 | AC2CA93F2400744200F0F6E1 /* Frameworks */ = {
95 | isa = PBXGroup;
96 | children = (
97 | );
98 | name = Frameworks;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXNativeTarget section */
104 | AC2CA9122400731E00F0F6E1 /* Example */ = {
105 | isa = PBXNativeTarget;
106 | buildConfigurationList = AC2CA9272400731E00F0F6E1 /* Build configuration list for PBXNativeTarget "Example" */;
107 | buildPhases = (
108 | AC2CA90F2400731E00F0F6E1 /* Sources */,
109 | AC2CA9102400731E00F0F6E1 /* Frameworks */,
110 | AC2CA9112400731E00F0F6E1 /* Resources */,
111 | );
112 | buildRules = (
113 | );
114 | dependencies = (
115 | );
116 | name = Example;
117 | packageProductDependencies = (
118 | AC2CA9402400744200F0F6E1 /* Localized */,
119 | );
120 | productName = LocalizedSwift;
121 | productReference = AC2CA9132400731E00F0F6E1 /* Example.app */;
122 | productType = "com.apple.product-type.application";
123 | };
124 | /* End PBXNativeTarget section */
125 |
126 | /* Begin PBXProject section */
127 | AC2CA90B2400731E00F0F6E1 /* Project object */ = {
128 | isa = PBXProject;
129 | attributes = {
130 | LastSwiftUpdateCheck = 1140;
131 | LastUpgradeCheck = 1140;
132 | ORGANIZATIONNAME = "Mario Iannotta";
133 | TargetAttributes = {
134 | AC2CA9122400731E00F0F6E1 = {
135 | CreatedOnToolsVersion = 11.4;
136 | LastSwiftMigration = 1140;
137 | };
138 | };
139 | };
140 | buildConfigurationList = AC2CA90E2400731E00F0F6E1 /* Build configuration list for PBXProject "LocalizedSwift" */;
141 | compatibilityVersion = "Xcode 9.3";
142 | developmentRegion = en;
143 | hasScannedForEncodings = 0;
144 | knownRegions = (
145 | en,
146 | Base,
147 | );
148 | mainGroup = AC2CA90A2400731E00F0F6E1;
149 | productRefGroup = AC2CA9142400731E00F0F6E1 /* Products */;
150 | projectDirPath = "";
151 | projectRoot = "";
152 | targets = (
153 | AC2CA9122400731E00F0F6E1 /* Example */,
154 | );
155 | };
156 | /* End PBXProject section */
157 |
158 | /* Begin PBXResourcesBuildPhase section */
159 | AC2CA9112400731E00F0F6E1 /* Resources */ = {
160 | isa = PBXResourcesBuildPhase;
161 | buildActionMask = 2147483647;
162 | files = (
163 | AC2CA93B2400734700F0F6E1 /* AnotherFile.strings in Resources */,
164 | AC2CA93C2400734700F0F6E1 /* Localizable.strings in Resources */,
165 | AC2CA9362400734700F0F6E1 /* Assets.xcassets in Resources */,
166 | AC2CA9352400734700F0F6E1 /* LaunchScreen.storyboard in Resources */,
167 | AC2CA93A2400734700F0F6E1 /* Main.storyboard in Resources */,
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | };
171 | /* End PBXResourcesBuildPhase section */
172 |
173 | /* Begin PBXSourcesBuildPhase section */
174 | AC2CA90F2400731E00F0F6E1 /* Sources */ = {
175 | isa = PBXSourcesBuildPhase;
176 | buildActionMask = 2147483647;
177 | files = (
178 | AC2CA93D2400734700F0F6E1 /* ViewController.swift in Sources */,
179 | AC2CA9382400734700F0F6E1 /* AppDelegate.swift in Sources */,
180 | );
181 | runOnlyForDeploymentPostprocessing = 0;
182 | };
183 | /* End PBXSourcesBuildPhase section */
184 |
185 | /* Begin XCBuildConfiguration section */
186 | AC2CA9252400731E00F0F6E1 /* Debug */ = {
187 | isa = XCBuildConfiguration;
188 | buildSettings = {
189 | ALWAYS_SEARCH_USER_PATHS = NO;
190 | CLANG_ANALYZER_NONNULL = YES;
191 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
192 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
193 | CLANG_CXX_LIBRARY = "libc++";
194 | CLANG_ENABLE_MODULES = YES;
195 | CLANG_ENABLE_OBJC_ARC = YES;
196 | CLANG_ENABLE_OBJC_WEAK = YES;
197 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
198 | CLANG_WARN_BOOL_CONVERSION = YES;
199 | CLANG_WARN_COMMA = YES;
200 | CLANG_WARN_CONSTANT_CONVERSION = YES;
201 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
202 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
203 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
204 | CLANG_WARN_EMPTY_BODY = YES;
205 | CLANG_WARN_ENUM_CONVERSION = YES;
206 | CLANG_WARN_INFINITE_RECURSION = YES;
207 | CLANG_WARN_INT_CONVERSION = YES;
208 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
209 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
210 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
211 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
212 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
213 | CLANG_WARN_STRICT_PROTOTYPES = YES;
214 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
215 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
216 | CLANG_WARN_UNREACHABLE_CODE = YES;
217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
218 | COPY_PHASE_STRIP = NO;
219 | DEBUG_INFORMATION_FORMAT = dwarf;
220 | ENABLE_STRICT_OBJC_MSGSEND = YES;
221 | ENABLE_TESTABILITY = YES;
222 | GCC_C_LANGUAGE_STANDARD = gnu11;
223 | GCC_DYNAMIC_NO_PIC = NO;
224 | GCC_NO_COMMON_BLOCKS = YES;
225 | GCC_OPTIMIZATION_LEVEL = 0;
226 | GCC_PREPROCESSOR_DEFINITIONS = (
227 | "DEBUG=1",
228 | "$(inherited)",
229 | );
230 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
231 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
232 | GCC_WARN_UNDECLARED_SELECTOR = YES;
233 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
234 | GCC_WARN_UNUSED_FUNCTION = YES;
235 | GCC_WARN_UNUSED_VARIABLE = YES;
236 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
237 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
238 | MTL_FAST_MATH = YES;
239 | ONLY_ACTIVE_ARCH = YES;
240 | SDKROOT = iphoneos;
241 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
242 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
243 | };
244 | name = Debug;
245 | };
246 | AC2CA9262400731E00F0F6E1 /* Release */ = {
247 | isa = XCBuildConfiguration;
248 | buildSettings = {
249 | ALWAYS_SEARCH_USER_PATHS = NO;
250 | CLANG_ANALYZER_NONNULL = YES;
251 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
253 | CLANG_CXX_LIBRARY = "libc++";
254 | CLANG_ENABLE_MODULES = YES;
255 | CLANG_ENABLE_OBJC_ARC = YES;
256 | CLANG_ENABLE_OBJC_WEAK = YES;
257 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
258 | CLANG_WARN_BOOL_CONVERSION = YES;
259 | CLANG_WARN_COMMA = YES;
260 | CLANG_WARN_CONSTANT_CONVERSION = YES;
261 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
262 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
263 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
264 | CLANG_WARN_EMPTY_BODY = YES;
265 | CLANG_WARN_ENUM_CONVERSION = YES;
266 | CLANG_WARN_INFINITE_RECURSION = YES;
267 | CLANG_WARN_INT_CONVERSION = YES;
268 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
269 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
270 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
273 | CLANG_WARN_STRICT_PROTOTYPES = YES;
274 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
275 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
276 | CLANG_WARN_UNREACHABLE_CODE = YES;
277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
278 | COPY_PHASE_STRIP = NO;
279 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
280 | ENABLE_NS_ASSERTIONS = NO;
281 | ENABLE_STRICT_OBJC_MSGSEND = YES;
282 | GCC_C_LANGUAGE_STANDARD = gnu11;
283 | GCC_NO_COMMON_BLOCKS = YES;
284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
286 | GCC_WARN_UNDECLARED_SELECTOR = YES;
287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
288 | GCC_WARN_UNUSED_FUNCTION = YES;
289 | GCC_WARN_UNUSED_VARIABLE = YES;
290 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
291 | MTL_ENABLE_DEBUG_INFO = NO;
292 | MTL_FAST_MATH = YES;
293 | SDKROOT = iphoneos;
294 | SWIFT_COMPILATION_MODE = wholemodule;
295 | SWIFT_OPTIMIZATION_LEVEL = "-O";
296 | VALIDATE_PRODUCT = YES;
297 | };
298 | name = Release;
299 | };
300 | AC2CA9282400731E00F0F6E1 /* Debug */ = {
301 | isa = XCBuildConfiguration;
302 | buildSettings = {
303 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
304 | CLANG_ENABLE_MODULES = YES;
305 | CODE_SIGN_STYLE = Automatic;
306 | DEVELOPMENT_TEAM = X9253HG4XT;
307 | INFOPLIST_FILE = "$(SRCROOT)/Example/Supporting files/Info.plist";
308 | LD_RUNPATH_SEARCH_PATHS = (
309 | "$(inherited)",
310 | "@executable_path/Frameworks",
311 | );
312 | MARKETING_VERSION = 1.0.2;
313 | PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.LocalizedSwift;
314 | PRODUCT_NAME = "$(TARGET_NAME)";
315 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
316 | SWIFT_VERSION = 5.0;
317 | TARGETED_DEVICE_FAMILY = "1,2";
318 | };
319 | name = Debug;
320 | };
321 | AC2CA9292400731E00F0F6E1 /* Release */ = {
322 | isa = XCBuildConfiguration;
323 | buildSettings = {
324 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
325 | CLANG_ENABLE_MODULES = YES;
326 | CODE_SIGN_STYLE = Automatic;
327 | DEVELOPMENT_TEAM = X9253HG4XT;
328 | INFOPLIST_FILE = "$(SRCROOT)/Example/Supporting files/Info.plist";
329 | LD_RUNPATH_SEARCH_PATHS = (
330 | "$(inherited)",
331 | "@executable_path/Frameworks",
332 | );
333 | MARKETING_VERSION = 1.0.2;
334 | PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.LocalizedSwift;
335 | PRODUCT_NAME = "$(TARGET_NAME)";
336 | SWIFT_VERSION = 5.0;
337 | TARGETED_DEVICE_FAMILY = "1,2";
338 | };
339 | name = Release;
340 | };
341 | /* End XCBuildConfiguration section */
342 |
343 | /* Begin XCConfigurationList section */
344 | AC2CA90E2400731E00F0F6E1 /* Build configuration list for PBXProject "LocalizedSwift" */ = {
345 | isa = XCConfigurationList;
346 | buildConfigurations = (
347 | AC2CA9252400731E00F0F6E1 /* Debug */,
348 | AC2CA9262400731E00F0F6E1 /* Release */,
349 | );
350 | defaultConfigurationIsVisible = 0;
351 | defaultConfigurationName = Release;
352 | };
353 | AC2CA9272400731E00F0F6E1 /* Build configuration list for PBXNativeTarget "Example" */ = {
354 | isa = XCConfigurationList;
355 | buildConfigurations = (
356 | AC2CA9282400731E00F0F6E1 /* Debug */,
357 | AC2CA9292400731E00F0F6E1 /* Release */,
358 | );
359 | defaultConfigurationIsVisible = 0;
360 | defaultConfigurationName = Release;
361 | };
362 | /* End XCConfigurationList section */
363 |
364 | /* Begin XCSwiftPackageProductDependency section */
365 | AC2CA9402400744200F0F6E1 /* Localized */ = {
366 | isa = XCSwiftPackageProductDependency;
367 | productName = Localized;
368 | };
369 | /* End XCSwiftPackageProductDependency section */
370 | };
371 | rootObject = AC2CA90B2400731E00F0F6E1 /* Project object */;
372 | }
373 |
--------------------------------------------------------------------------------