├── .ruby-version
├── .gitignore
├── Gemfile
├── LocalizationHelperDemo
├── LocalizationHelperDemo
│ ├── ar.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── he-IL.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── ur.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── agq-CM.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── ckb-IQ.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── ckb-IR.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── globe.imageset
│ │ │ ├── png-transparent-community-world-internationalization-translation-service-paises-glass-service-innovation.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── arrow-right.png
│ ├── en.lproj
│ │ ├── Localizable.strings
│ │ └── Main.strings
│ ├── Base.lproj
│ │ ├── Localizable.strings
│ │ ├── LaunchScreen.storyboard
│ │ ├── LaunchScreen (1).storyboard
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── StackViewTestViewController.swift
│ ├── InformationTextView.xib
│ └── ViewController.swift
└── LocalizationHelperDemo.xcodeproj
│ ├── xcuserdata
│ ├── moathaliwat.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ └── LocalizationHelperDemo.xcscheme
│ └── moath.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ ├── deya.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── dhamza.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── molhWithMultipleScenese
├── molhWithMultipleScenese
│ ├── ar.lproj
│ │ ├── LaunchScreen.strings
│ │ ├── Main.strings
│ │ └── Localizable.strings
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── en.lproj
│ │ └── Localizable.strings
│ ├── ViewController.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ ├── Info.plist
│ └── SceneDelegate.swift
└── molhWithMultipleScenese.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ └── xcschemes
│ │ └── molhWithMultipleScenese.xcscheme
│ └── project.pbxproj
├── Tests
├── LinuxMain.swift
└── MOLHTests
│ ├── XCTestManifests.swift
│ └── MOLHTests.swift
├── MOLH.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── MOLH_Info.plist
├── MOLHTests_Info.plist
├── xcshareddata
│ └── xcschemes
│ │ └── MOLH-Package.xcscheme
└── project.pbxproj
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── Sources
└── MOLH
│ ├── MOLHFont.swift
│ ├── MOLHSizable.swift
│ ├── MOLHFontLocalizableViews.swift
│ ├── MOLHLanguage.swift
│ └── MOLH.swift
├── MOLH.podspec
├── LICENSE
├── Package.swift
├── Gemfile.lock
├── README.md
└── post.md
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.4.5
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | xcuserdata/
5 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "cocoapods"
4 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ar.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/he-IL.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ur.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/ar.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/agq-CM.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IQ.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IR.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import MOLHTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += MOLHTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/arrow-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoathOthman/MOLH/HEAD/LocalizationHelperDemo/LocalizationHelperDemo/arrow-right.png
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/ar.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UILabel"; text = "Label"; ObjectID = "w3U-9c-GpQ"; */
3 | "w3U-9c-GpQ.text" = "Label";
4 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/MOLHTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(MOLHTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/xcuserdata/moathaliwat.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ur.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please urdu";
9 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | molhWithMultipleScenese
4 |
5 | Created by Moath_Othman on 4/25/20.
6 | Copyright © 2020 moath. All rights reserved.
7 | */
8 | "localize me please" = "localize me please";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/agq-CM.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please cameroon";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IQ.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please sorani";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IR.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please sorani";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/he-IL.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please hebrew";
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/xcuserdata/deya.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoathOthman/MOLH/HEAD/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/xcuserdata/deya.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/xcuserdata/dhamza.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoathOthman/MOLH/HEAD/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/xcuserdata/dhamza.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/MOLH.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Assets.xcassets/globe.imageset/png-transparent-community-world-internationalization-translation-service-paises-glass-service-innovation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoathOthman/MOLH/HEAD/LocalizationHelperDemo/LocalizationHelperDemo/Assets.xcassets/globe.imageset/png-transparent-community-world-internationalization-translation-service-paises-glass-service-innovation.png
--------------------------------------------------------------------------------
/Tests/MOLHTests/MOLHTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import MOLH
3 |
4 | final class MOLHTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | }
10 |
11 | static var allTests = [
12 | ("testExample", testExample),
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ar.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "لوكالايز مي";
9 | "stack_view_label_1" = " باعالربيStack view label one content somhow a bit longer than usual to accomodate 2 lines";
10 | "stack_view_label_2" = "بيStack view label two";
11 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Base.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | Localization102
4 |
5 | Created by Moath_Othman on 3/6/16.
6 | Copyright © 2016 Moath_Othman. All rights reserved.
7 | */
8 | "localize_me_please" = "localize me please base";
9 | "stack_view_label_1" = "Stack view label one content somhow a bit longer than usual to accomodate 2 lines";
10 | "stack_view_label_2" = "Stack view label two";
11 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/ar.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | molhWithMultipleScenese
4 |
5 | Created by Moath_Othman on 4/25/20.
6 | Copyright © 2020 moath. All rights reserved.
7 | */
8 | /*
9 | Localizable.strings
10 | Localization102
11 |
12 | Created by Moath_Othman on 3/6/16.
13 | Copyright © 2016 Moath_Othman. All rights reserved.
14 | */
15 | "localize me please" = "arabic localizartion";
16 |
--------------------------------------------------------------------------------
/Sources/MOLH/MOLHFont.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MOLHFont.swift
3 | // Demo
4 | //
5 | // Created by Moath_Othman on 1/27/17.
6 | // Copyright © 2017 Moath. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public class MOLHFont {
13 | public static let shared = MOLHFont()
14 | /// Font for arabic language this variable and public
15 | public var arabic: UIFont = UIFont.systemFont(ofSize: 12)
16 | public var english: UIFont = UIFont.systemFont(ofSize: 12)
17 | }
18 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Assets.xcassets/globe.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "filename" : "png-transparent-community-world-internationalization-translation-service-paises-glass-service-innovation.png",
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/xcuserdata/moath.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | LocalizationHelperDemo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | EC5B8FE71EE0ECA4003BE809
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/MOLH_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/MOLHTests_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | BNDL
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MOLH.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 |
4 |
5 | s.name = "MOLH"
6 | s.version = "1.4.3"
7 | s.summary = "Localization helper for iOS apps mainly focusing on the LTR/RTL issue Edit"
8 |
9 | s.description = <<-DESC
10 | Localization helper for iOS apps mainly focusing on the LTR/RTL issue Edit
11 | DESC
12 |
13 | s.homepage = "https://github.com/MoathOthman/MOLH"
14 |
15 | s.license = { :type => "MIT", :file => "LICENSE" }
16 |
17 |
18 | s.author = { "moath othman" => "myopenworld@outlook.com" }
19 |
20 | s.social_media_url = "http://twitter.com/dark_torch"
21 |
22 | s.platform = :ios, "9.0"
23 |
24 |
25 | s.source = { :git => "https://github.com/MoathOthman/MOLH.git", :tag => "v"+s.version.to_s }
26 |
27 |
28 | s.source_files = "Sources/MOLH/*.swift"
29 |
30 |
31 | s.requires_arc = true
32 |
33 | s.swift_version = '5.0'
34 | end
35 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // molhWithMultipleScenese
4 | //
5 | // Created by Moath_Othman on 4/25/20.
6 | // Copyright © 2020 moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 | @IBOutlet weak var programmaticallylocalizedLabel: UILabel!
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 |
17 |
18 | self.programmaticallylocalizedLabel.text = NSLocalizedString("localize me please", comment: "Localize me Label in the main scene")
19 | // Do any additional setup after loading the view.
20 | }
21 | @IBAction func switchTheLanguage(_ sender: UIButton) {
22 | MOLH.setLanguageTo(MOLHLanguage.currentAppleLanguage() == "en" ? "ar" : "en")
23 | MOLH.reset(transition: .transitionCrossDissolve)
24 | }
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/agq-CM.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "CAMERA";
10 |
11 | /* Class = "UITextField"; placeholder = "TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "CAMERON Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "CAMERON Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "CAMERON ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ur.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "Main View";
10 |
11 | /* Class = "UITextField"; placeholder = "TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "TextField Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "Go to Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "Second ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IQ.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "Main View";
10 |
11 | /* Class = "UITextField"; placeholder = "TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "TextField Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "Go to Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "Second ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ckb-IR.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "Main View";
10 |
11 | /* Class = "UITextField"; placeholder = "TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "TextField Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "Go to Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "Second ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/he-IL.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "Main View";
10 |
11 | /* Class = "UITextField"; placeholder = "TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "TextField Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "Go to Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "Second ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/en.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "Hello ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "Main View";
10 |
11 | /* Class = "UITextField"; placeholder = "Centered TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "TextField Case";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "Go to Second View";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "Second ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ar.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UIButton"; normalTitle = "Switch Language"; ObjectID = "Cje-ky-EQg"; */
3 | "Cje-ky-EQg.normalTitle" = "Switch Language";
4 |
5 | /* Class = "UILabel"; text = "Hello "; ObjectID = "XqB-5F-EF1"; */
6 | "XqB-5F-EF1.text" = "مرحبا ";
7 |
8 | /* Class = "UINavigationItem"; title = "Main View"; ObjectID = "eV5-Ly-eMc"; */
9 | "eV5-Ly-eMc.title" = "الصفحة الرئيسية";
10 |
11 | /* Class = "UITextField"; placeholder = "Centered TextField Case"; ObjectID = "fiM-aM-EMW"; */
12 | "fiM-aM-EMW.placeholder" = "حقل بيانات";
13 |
14 | /* Class = "UIButton"; normalTitle = "Go to Second View"; ObjectID = "jMW-hU-lgc"; */
15 | "jMW-hU-lgc.normalTitle" = "اذهب الى الصفحة التالية";
16 |
17 | /* Class = "UIViewController"; title = "Second "; ObjectID = "oPo-J9-SrU"; */
18 | "oPo-J9-SrU.title" = "الثاني ";
19 |
20 | /* Class = "UILabel"; text = "Label"; ObjectID = "qa0-jT-D1A"; */
21 | "qa0-jT-D1A.text" = "Label";
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Moath othman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/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: "MOLH",
8 | platforms: [
9 | .iOS(.v10)
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: "MOLH",
15 | targets: ["MOLH"]),
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: "MOLH",
26 | dependencies: []),
27 | .testTarget(
28 | name: "MOLHTests",
29 | dependencies: ["MOLH"]),
30 | ]
31 | )
32 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LocalizationHelperDemo
4 | //
5 | // Created by Moath_Othman on 6/2/17.
6 | // Copyright © 2017 Moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate, MOLHResetable {
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 | MOLHFont.shared.arabic = UIFont(name: "Courier", size: 13)!
19 | MOLHLanguage.setDefaultLanguage("ar")
20 | MOLH.shared.activate(true)
21 |
22 | MOLH.shared.specialKeyWords = ["Cancel","Done"]
23 | reset()
24 | return true
25 | }
26 |
27 | func reset() {
28 | let rootViewController: UIWindow = ((UIApplication.shared.delegate?.window)!)!
29 | let story = UIStoryboard(name: "Main", bundle: nil)
30 | rootViewController.rootViewController = story.instantiateViewController(withIdentifier: "rootnav")
31 | }
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
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 |
38 |
39 |
--------------------------------------------------------------------------------
/Sources/MOLH/MOLHSizable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MOLHSizable.swift
3 | // Demo
4 | //
5 | // Created by Moath_Othman on 2/5/17.
6 | // Copyright © 2017 Moath. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public enum DeviceWidthtype {
13 | case fouror3
14 | case four7
15 | case five5
16 |
17 | static var type: DeviceWidthtype {
18 | let width = UIScreen.main.bounds.width
19 | if width >= 414 {
20 | return .five5
21 | } else if width >= 375 {
22 | return .four7
23 | } else {
24 | return .fouror3
25 | }
26 | }
27 | }
28 |
29 |
30 | open class MOLHSizableLayoutConstraint: NSLayoutConstraint {
31 | var fourDeduction: CGFloat = 0.0
32 | var fourSevenDeduction: CGFloat = 0.0
33 | open override var constant: CGFloat {
34 | get {
35 | let c = super.constant
36 | var sizedConstant = c
37 | switch DeviceWidthtype.type {
38 | case .fouror3:
39 | sizedConstant -= c * self.fourDeduction
40 | break
41 | case .four7:
42 | sizedConstant -= c * self.fourSevenDeduction
43 | break
44 | case .five5:
45 | break
46 | }
47 | return sizedConstant
48 | }
49 | set {
50 | super.constant = newValue
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/Base.lproj/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 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Base.lproj/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 |
27 |
28 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Base.lproj/LaunchScreen (1).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 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/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 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // molhWithMultipleScenese
4 | //
5 | // Created by Moath_Othman on 4/25/20.
6 | // Copyright © 2020 moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate, MOLHResetable {
13 | var window: UIWindow?
14 |
15 |
16 | func reset() {
17 | let stry = UIStoryboard(name: "Main", bundle: nil)
18 | window?.rootViewController = stry.instantiateInitialViewController()
19 | }
20 |
21 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
22 |
23 | MOLHFont.shared.arabic = UIFont(name: "Courier", size: 13)!
24 | MOLHLanguage.setDefaultLanguage("ar")
25 | MOLH.shared.activate(true)
26 | MOLH.shared.specialKeyWords = ["Cancel","Done"]
27 |
28 | // Override point for customization after application launch.
29 | return true
30 | }
31 |
32 | // MARK: UISceneSession Lifecycle
33 |
34 | @available(iOS 13.0, *)
35 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
36 | // Called when a new scene session is being created.
37 | // Use this method to select a configuration to create the new scene with.
38 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
39 | }
40 |
41 | @available(iOS 13.0, *)
42 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
43 | // Called when the user discards a scene session.
44 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
45 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
46 | }
47 |
48 |
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/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 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.1)
5 | activesupport (4.2.11.1)
6 | i18n (~> 0.7)
7 | minitest (~> 5.1)
8 | thread_safe (~> 0.3, >= 0.3.4)
9 | tzinfo (~> 1.1)
10 | algoliasearch (1.27.1)
11 | httpclient (~> 2.8, >= 2.8.3)
12 | json (>= 1.5.1)
13 | atomos (0.1.3)
14 | claide (1.0.3)
15 | cocoapods (1.8.4)
16 | activesupport (>= 4.0.2, < 5)
17 | claide (>= 1.0.2, < 2.0)
18 | cocoapods-core (= 1.8.4)
19 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
20 | cocoapods-downloader (>= 1.2.2, < 2.0)
21 | cocoapods-plugins (>= 1.0.0, < 2.0)
22 | cocoapods-search (>= 1.0.0, < 2.0)
23 | cocoapods-stats (>= 1.0.0, < 2.0)
24 | cocoapods-trunk (>= 1.4.0, < 2.0)
25 | cocoapods-try (>= 1.1.0, < 2.0)
26 | colored2 (~> 3.1)
27 | escape (~> 0.0.4)
28 | fourflusher (>= 2.3.0, < 3.0)
29 | gh_inspector (~> 1.0)
30 | molinillo (~> 0.6.6)
31 | nap (~> 1.0)
32 | ruby-macho (~> 1.4)
33 | xcodeproj (>= 1.11.1, < 2.0)
34 | cocoapods-core (1.8.4)
35 | activesupport (>= 4.0.2, < 6)
36 | algoliasearch (~> 1.0)
37 | concurrent-ruby (~> 1.1)
38 | fuzzy_match (~> 2.0.4)
39 | nap (~> 1.0)
40 | cocoapods-deintegrate (1.0.4)
41 | cocoapods-downloader (1.3.0)
42 | cocoapods-plugins (1.0.0)
43 | nap
44 | cocoapods-search (1.0.0)
45 | cocoapods-stats (1.1.0)
46 | cocoapods-trunk (1.4.1)
47 | nap (>= 0.8, < 2.0)
48 | netrc (~> 0.11)
49 | cocoapods-try (1.1.0)
50 | colored2 (3.1.2)
51 | concurrent-ruby (1.1.5)
52 | escape (0.0.4)
53 | fourflusher (2.3.1)
54 | fuzzy_match (2.0.4)
55 | gh_inspector (1.1.3)
56 | httpclient (2.8.3)
57 | i18n (0.9.5)
58 | concurrent-ruby (~> 1.0)
59 | json (2.3.1)
60 | minitest (5.13.0)
61 | molinillo (0.6.6)
62 | nanaimo (0.2.6)
63 | nap (1.1.0)
64 | netrc (0.11.0)
65 | ruby-macho (1.4.0)
66 | thread_safe (0.3.6)
67 | tzinfo (1.2.5)
68 | thread_safe (~> 0.1)
69 | xcodeproj (1.13.0)
70 | CFPropertyList (>= 2.3.3, < 4.0)
71 | atomos (~> 0.1.3)
72 | claide (>= 1.0.2, < 2.0)
73 | colored2 (~> 3.1)
74 | nanaimo (~> 0.2.6)
75 |
76 | PLATFORMS
77 | ruby
78 |
79 | DEPENDENCIES
80 | cocoapods
81 |
82 | BUNDLED WITH
83 | 1.17.3
84 |
--------------------------------------------------------------------------------
/Sources/MOLH/MOLHFontLocalizableViews.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MOLHFontLocalizableViews.swift
3 | // Demo
4 | //
5 | // Created by Moath_Othman on 1/27/17.
6 | // Copyright © 2017 Moath. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public protocol MOLHFontable {
13 | func updateFont()
14 | }
15 |
16 | extension UIButton: MOLHFontable {
17 | public func updateFont() {
18 | if MOLHLanguage.isArabic() {
19 | titleLabel?.font = UIFont(name: MOLHFont.shared.arabic.fontName, size: titleLabel?.font.pointSize ?? 0)
20 | }
21 | }
22 | }
23 |
24 | extension UILabel: MOLHFontable {
25 | public func updateFont() {
26 | if MOLHLanguage.isArabic() && !MOLHLanguage.hasEnglishText(text: self.text ?? "") {
27 | self.font = UIFont(name: MOLHFont.shared.arabic.fontName, size: font.pointSize)
28 | }
29 | }
30 | }
31 |
32 |
33 | extension UITextField: MOLHFontable {
34 | public func updateFont() {
35 | if MOLHLanguage.isArabic() && !MOLHLanguage.hasEnglishText(text: self.text ?? "") {
36 | font = UIFont(name: MOLHFont.shared.arabic.fontName, size: font?.pointSize ?? 0)
37 | }
38 | }
39 | }
40 |
41 | extension UITextView: MOLHFontable {
42 | public func updateFont() {
43 | if MOLHLanguage.isArabic() && !MOLHLanguage.hasEnglishText(text: self.text) {
44 | font = UIFont(name: MOLHFont.shared.arabic.fontName, size: font?.pointSize ?? 0)
45 | }
46 | }
47 | }
48 |
49 | open class MOLHFontLocalizableButton: UIButton {
50 | override open func awakeFromNib() {
51 | super.awakeFromNib()
52 | updateFont()
53 | }
54 | }
55 |
56 | open class MOLHFontLocalizableLabel: UILabel {
57 | override open func awakeFromNib() {
58 | super.awakeFromNib()
59 | }
60 | override open var text: String? {
61 | didSet {
62 | updateFont()
63 | }
64 | }
65 | }
66 |
67 | open class MOLHFontLocalizableTextField: UITextField {
68 | override open func awakeFromNib() {
69 | super.awakeFromNib()
70 | }
71 | override open var text: String? {
72 | didSet {
73 | updateFont()
74 | }
75 | }
76 | }
77 |
78 | open class MOLHFontLocalizableTextView: UITextView {
79 | override open func awakeFromNib() {
80 | super.awakeFromNib()
81 | }
82 | override open var text: String? {
83 | didSet {
84 | updateFont()
85 | }
86 | }
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MOLH
2 | Localization helper for iOS apps mainly focusing on the LTR/RTL issue
3 |
4 | # Install
5 | Add `pod 'MOLH'` to your podfile. (check https://cocoapods.org/ for more info about cocoapods)
6 |
7 | You can install it through Swift package manager as well.
8 |
9 | # How To Use
10 | `import MOLH`
11 |
12 | ### Start
13 | When you start the app
14 |
15 | `MOLH.shared.activate(true)`
16 |
17 | **Make sure this method is called only once and not on every reset**
18 |
19 | or
20 |
21 | `MOLH.shared.activate(false)` to not use swizzling and use subclassing from MOLH* UI classes.
22 |
23 | ### To reset the language
24 |
25 | ```
26 | MOLH.setLanguageTo(MOLHLanguage.currentAppleLanguage() == "en" ? "ar" : "en")
27 | MOLH.reset()
28 | ```
29 |
30 | ### Set default
31 | Before *.activate* set
32 |
33 | `MOLHLanguage.setDefaultLanguage("ar")`
34 |
35 | ### using without swizzling (prefered)
36 | you can choose to not use swizzling `MOLH.shared.activate(false)` , in that case you subclass MOLH-UI Subclasses , like `MOLHTextField` , this will give you more controlability as you can by-pass the *tag* requirement by using `forceSwitchingRegardlessOfTag` and set it to true.
37 |
38 | ## Images
39 | To make sure an image is flipped when switching to RTL or to LTR, you can use `flipIfNeeded()` function on image or `UIImage().imageFlippedForRightToLeftLayoutDirection()`
40 |
41 | ### Fonts
42 | Its better to have the app fonts in one place in your app, e.g. a **FontManager**. and there you can decide which font to use based on the chosen language, this would be the eaiser way.
43 |
44 | ### Other Frameworks and bundles
45 | Some controls such as ActionSheetDatePicker have locale property so you can set them appropriately e.g.
46 |
47 | `actionSheetDatePicker?.locale = Locale(identifier: MOLHLanguage.currentLocaleIdentifier())`
48 |
49 | ## Common Issues
50 | ### Collection view content are flipped in a non readable way
51 | use this line to solve it
52 | `collectionView.semanticContentAttribute = .unspecified`
53 | Thanks to [didats](https://github.com/didats)
54 |
55 | you may check [this post](https://medium.com/@dark_torch/working-with-localization-in-swift-part-2-e7c8a660eb2a).
56 |
57 | ### uilabel/uitextfield are not reflecting
58 | make sure to set the tag and make sure the .activate method is only called once and not on every reset
59 |
60 | # Author
61 | * Twitter : [dark_torch](https://twitter.com/dark_torch)
62 | * Website: https://moathothman.com
63 | * Check my app PuzzPic http://apple.co/2a6Ow8W
64 |
65 | # Support the library
66 | If you enjoy MOLH and I want to say thank you, you can (buy me a coffee)[https://www.buymeacoffee.com/moathothman]
67 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/xcshareddata/xcschemes/MOLH-Package.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
54 |
60 |
61 |
63 |
64 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // molhWithMultipleScenese
4 | //
5 | // Created by Moath_Othman on 4/25/20.
6 | // Copyright © 2020 moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 |
12 | @available(iOS 13.0, *)
13 | class SceneDelegate: UIResponder, UIWindowSceneDelegate, MOLHResetable {
14 |
15 | var window: UIWindow?
16 |
17 | func reset() {
18 | let stry = UIStoryboard(name: "Main", bundle: nil)
19 | window?.rootViewController = stry.instantiateInitialViewController()
20 | }
21 |
22 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
23 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
24 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
25 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
26 | guard let _ = (scene as? UIWindowScene) else { return }
27 |
28 | }
29 |
30 | func sceneDidDisconnect(_ scene: UIScene) {
31 | // Called as the scene is being released by the system.
32 | // This occurs shortly after the scene enters the background, or when its session is discarded.
33 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
34 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
35 | }
36 |
37 | func sceneDidBecomeActive(_ scene: UIScene) {
38 | // Called when the scene has moved from an inactive state to an active state.
39 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
40 | }
41 |
42 | func sceneWillResignActive(_ scene: UIScene) {
43 | // Called when the scene will move from an active state to an inactive state.
44 | // This may occur due to temporary interruptions (ex. an incoming phone call).
45 | }
46 |
47 | func sceneWillEnterForeground(_ scene: UIScene) {
48 | // Called as the scene transitions from the background to the foreground.
49 | // Use this method to undo the changes made on entering the background.
50 | }
51 |
52 | func sceneDidEnterBackground(_ scene: UIScene) {
53 | // Called as the scene transitions from the foreground to the background.
54 | // Use this method to save data, release shared resources, and store enough scene-specific state information
55 | // to restore the scene back to its current state.
56 | }
57 |
58 |
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese.xcodeproj/xcshareddata/xcschemes/molhWithMultipleScenese.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 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/xcuserdata/moathaliwat.xcuserdatad/xcschemes/LocalizationHelperDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/StackViewTestViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StackViewTestViewController.swift
3 | // LocalizationHelperDemo
4 | //
5 | // Created by Moath_Othman on 5/3/22.
6 | // Copyright © 2022 Moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class StackViewTestViewController: UIViewController {
12 |
13 | @IBOutlet var label2: UILabel!
14 | @IBOutlet var label1: UILabel!
15 | private let noContentTextView = InformationTextView()
16 |
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 |
20 | label1.text = NSLocalizedString("stack_view_label_1", comment: "")
21 | label2.text = NSLocalizedString("stack_view_label_2", comment: "")
22 | }
23 |
24 | override func viewDidAppear(_ animated: Bool) {
25 | super.viewDidAppear(animated)
26 | // showNoContentView()
27 | }
28 |
29 | func showNoContentView() {
30 | noContentTextView.configure(text: "LocalizeLocalizeLocalize LocalizeLocalizeLocalize LocalizeLocalize Localize.no_apps_linked_disclaimer()")
31 | view.addSubview(noContentTextView)
32 |
33 | noContentTextView.translatesAutoresizingMaskIntoConstraints = false
34 | NSLayoutConstraint.activate([
35 | noContentTextView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
36 | noContentTextView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
37 | noContentTextView.heightAnchor.constraint(equalToConstant: 150),
38 | noContentTextView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
39 | ])
40 | }
41 |
42 | func hideNoContentView() {
43 | noContentTextView.removeFromSuperview()
44 | }
45 | }
46 |
47 | @IBDesignable
48 | final class InformationTextView: NibBasedView {
49 |
50 | @IBOutlet private var textLabel: UILabel!
51 |
52 | func configure(text: String) {
53 | self.textLabel.text = text
54 | setup()
55 | }
56 |
57 | override func awakeFromNib() {
58 | super.awakeFromNib()
59 | setup()
60 | }
61 |
62 | func setup() {
63 | textLabel.numberOfLines = 0
64 | textLabel.lineBreakMode = .byWordWrapping
65 | textLabel.tag = -1
66 | backgroundColor = .clear
67 |
68 | textLabel.text = "Verhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad terhoi wlog io sad te "
69 | }
70 |
71 | }
72 |
73 |
74 | class NibBasedView: UIView {
75 |
76 | @IBOutlet private var contentView: UIView!
77 |
78 | override init(frame: CGRect) {
79 | super.init(frame: frame)
80 | loadNib()
81 | }
82 |
83 | required init?(coder aDecoder: NSCoder) {
84 | super.init(coder: aDecoder)
85 | if subviews.isEmpty {
86 | loadNib()
87 | }
88 | }
89 |
90 | private func loadNib() {
91 | let ttt = type(of: self)
92 | let classString = String(describing: ttt)
93 | let bundle = Bundle(for: ttt)
94 |
95 | if UINib(nibName: classString, bundle: bundle).instantiate(
96 | withOwner: self,
97 | options: nil).first as? UIView != nil {
98 |
99 | addSubview(contentView)
100 | contentView.translatesAutoresizingMaskIntoConstraints = false
101 | NSLayoutConstraint.activate([
102 | contentView.topAnchor.constraint(equalTo: topAnchor),
103 | contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
104 | contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
105 | contentView.trailingAnchor.constraint(equalTo: trailingAnchor)
106 | ])
107 | }
108 |
109 | style()
110 | }
111 |
112 | func style() {
113 | contentView.backgroundColor = .clear
114 | backgroundColor = .clear
115 |
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/post.md:
--------------------------------------------------------------------------------
1 | Working with localization in swift part 2
2 | Last year i write a post about localization covering some issues like switching language and right-to-left / left-to-right dilemma.
3 |
4 | In this post am going to introduce a small library to do the heavy lifting for you.
5 |
6 | The goals
7 | The main goals are
8 |
9 | Switching the language without a restart.
10 | Switching layout direction and semantics based on the language RTL/LTR.
11 | Avoid duplication (nibs,stories)
12 | Simplicity (for real!!)
13 | LocalizationHelper (MOLH)
14 | LocalizationHelper is a small library to help you with the daunting issues that comes when you are dealing with more than one language where some of them are RTL languages and another's are LTR languages.
15 |
16 | You can download the repository from here , which has a demo app within it.
17 |
18 | to install MOLH through Pods add
19 |
20 | pod 'MOLH'
21 | to your podfile. (check https://cocoapods.org/ for more info about cocoapods)
22 |
23 | How to use
24 |
25 | in the Appdelegate `didFinishLaunchingWithOptions` method add
26 |
27 | MOLH.shared.activate(true)
28 | ‘True’ to use swizzling, leaving most of the work on MOLH, otherwise you have to do some extra work. We will go through that.
29 |
30 | Enable localization
31 |
32 | Add Localizable.strings file
33 | Project -> YOUR_PROJECT_NAME -> localization -> hit the plus language and add YOUR_LANGUAGE in our demo we add Arabic as its an RTL language.
34 | Lastly add some text in the strings files in this format
35 | ` “TextToLocalize” = “itsLocalization”;
36 |
37 | You may add localization for storyboard and/or xibs , but I don’t advise that , it will become hard later to modify them. so it’s better to stick with the strings file.
38 | Take effect
39 | The kind of views that are affected by MOLH are UIControl, UILabel, UITextField,UITextView,UIImageView,UIButton. These views are affected by the RTL/LTR e.g. textAlignment , control alignment and UIImage direction.
40 |
41 | If you are not using swizzling then use the appropriate subclass from MOLH e.g. MOLHLabel.
42 |
43 | The most important factor for a view here is the tag .
44 |
45 | If it's less than zero MOLH will consider that it wishes to adapt the natural direction and it will be affected. By default all views have zero tag and hence not affected, so it’s an opt-in feature.
46 |
47 | For the autolayout flipping you don’t need to do anything. Though, to opt-out, then from attribute inspector click on one of the items and uncheck “Respect language direction” .
48 |
49 | Custom Views
50 | For your custom views and custom layout you may need to check for the language manually and there you can use
51 |
52 | MOLHLanguage.isRTL()
53 | function.
54 |
55 | e.g.
56 |
57 | if MOLHLanguage.isRTL() {
58 | titleLabel?.font = UIFont.appSettingNotSelectedFontArabi()
59 | }
60 | Change the language
61 | You probably have somewhere in your app a change language button/cell/…
62 |
63 | in that function call you need to call setLanguage “accept with locale like en-us” and reset. e.g.
64 |
65 | MOLH.setLanguageTo(MOLHLanguage.currentAppleLanguage() == “en” ? “ar” : “en”)
66 | MOLH.reset()
67 | back to Appdelegate.swift , add conformance to MOLHResetable, and implement the reset function. It’s better IMO to handle reloading viewcontrollers in somewhere close to the Appdelegate.
68 |
69 | Other Frameworks and bundles
70 | MOLH currently affects the app bundle only, and since other frameworks may have UI elements with their localization bundled with them, MOLH can’t access them and reload them.
71 |
72 | Some controls such as ActionSheetDatePicker have locale property so you can set them appropriately e.g.
73 |
74 | actionSheetDatePicker?.locale = Locale(identifier: MOLHLanguage.currentLocaleIdentifier())
75 | others don’t, and in that case you need to handle their localization yourself and simply tell MOLH that those words will be handled by the app bundle. you can do that using specialKeyWords
76 |
77 | MOLH.shared.specialKeyWords = [“Cancel”,”Done”]
78 | where cancel and done are strings used by another bundle and you are providing localizations for them in your Localizable.string.
79 |
80 | Fonts
81 | it’s possible using MOLHFont to specify an arabic font e.g.
82 |
83 | MOLHFont.shared.arabic = R.font.winSoftProMedium(size: 18)!
84 | and there is a method you can use on UIButton,UITextField,UILabel,UITextView called updatefont(), that you can call to change the font into arabic if needed , currently MOLH support specifing arabic font, since I haven’t used another languages tbh :/.
85 |
86 | or you may inherit from MOLHFont.
87 |
88 | Finale
89 | MOLH helped me in a couple of a production apps , I hope it does for you too:). Its far from complete solution and contribution is very welcome.
90 | Happy Coding.
91 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/InformationTextView.xib:
--------------------------------------------------------------------------------
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 |
29 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Sources/MOLH/MOLHLanguage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // L102Language.swift
3 | // Localization102
4 | //
5 | // Created by Moath_Othman on 2/24/16.
6 | // Copyright © 2016 Moath_Othman. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// constants
12 | private let APPLE_LANGUAGE_KEY = "AppleLanguages"
13 | private let MOLHFirstTimeLanguage = "plhfirsttimelanguage"
14 | /**
15 | **MOLHLanguage** is responsible for getting and setting the language.
16 | - fetch current language without locale
17 | - get current language with locale
18 | - set current language
19 | - set default language
20 | - check if current language is RTL
21 | - check if current language is Arabic
22 | - check if a text has english chars
23 |
24 | @auther Moath Othman
25 | */
26 | open class MOLHLanguage {
27 | public static let shared = MOLHLanguage()
28 |
29 | /// get current Apple language
30 | public class func currentAppleLanguage() -> String {
31 | let current = preferredLanguage.first!
32 | if let hyphenIndex = current.firstIndex(of: "-") {
33 | return String(current[.. String {
44 | let current = preferredLanguage.first!
45 | return current
46 | }
47 |
48 | /// set @lang to be the first in AppleLanguages list, note this method does not switch the language currently, u still need to restart the app, use MOLH.setLanguageTo instead
49 | public class func setAppleLanguageTo(_ lang: String) {
50 | let userDefaults = UserDefaults.standard
51 | userDefaults.set([lang,currentAppleLanguage()], forKey: APPLE_LANGUAGE_KEY)
52 | userDefaults.synchronize()
53 | }
54 |
55 | /**
56 | Set the default language
57 |
58 | @param language string
59 |
60 | @return void
61 | */
62 | public class func setDefaultLanguage(_ language: String) {
63 | if !UserDefaults.standard.bool(forKey: MOLHFirstTimeLanguage) {
64 | MOLH.setLanguageTo(language)
65 | UserDefaults.standard.set(true, forKey: MOLHFirstTimeLanguage)
66 | }
67 | }
68 |
69 | /**
70 | **Check if the current language is Arabic**
71 | @description see if the prefix of the language is ar
72 |
73 | @return is arabic boolean
74 | */
75 | public class func isArabic() -> Bool {
76 | return currentAppleLanguage() == "ar"
77 | }
78 |
79 | /**
80 | **Check the current Layout direction is right to left**
81 |
82 | @return boolean
83 | */
84 | @available(*, deprecated, message: "Use isRTLLanguage")
85 | public static func isRTL() -> Bool {
86 | return isRTLLanguage()
87 | }
88 |
89 | /**
90 | Check if the text is english text
91 |
92 | @param text to be checked
93 |
94 | @return true of it has english text
95 | */
96 | public static func hasEnglishText(text: String) -> Bool {
97 | return text.rangeOfCharacter(from: CharacterSet(charactersIn: "1234567890poiuytrewqasdfghjklmnbvcxz")) != nil
98 | }
99 |
100 | /**
101 | Check if the current language is a right to left language
102 |
103 | @return true if its a right to left language
104 | */
105 | public static func isRTLLanguage() -> Bool {
106 | return !RTLLanguages.filter{$0 == currentLocaleIdentifier() || $0 == currentAppleLanguage()}.isEmpty
107 | }
108 |
109 | /**
110 | Check if the current language is a right to left language
111 |
112 | @param language to be tested
113 |
114 | @return true if its a right to left language
115 | */
116 | public static func isRTLLanguage(language: String) -> Bool {
117 | return !RTLLanguages.filter{language == $0}.isEmpty
118 | }
119 |
120 | private static let RTLLanguages = ["ar",
121 | "fa",
122 | "he",
123 | "ckb-IQ",
124 | "ckb-IR",
125 | "ur",
126 | "ckb",
127 | "ku"]
128 |
129 | private static var preferredLanguage: [String] {
130 | let userDefaults = UserDefaults.standard
131 | let langArray = userDefaults.object(forKey: APPLE_LANGUAGE_KEY)
132 | return langArray as? [String] ?? []
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // LocalizationHelperDemo
4 | //
5 | // Created by Moath_Othman on 6/2/17.
6 | // Copyright © 2017 Moath. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 | @IBOutlet weak var programmaticallylocalizedLabel: UILabel!
13 | @IBOutlet var labelWithFont: MOLHFontLocalizableLabel!
14 | @IBOutlet var textField: TextView!
15 | @IBOutlet var arrowImage: UIImageView! {
16 | didSet {
17 | arrowImage.image = arrowImage.image?.flipIfNeeded()
18 | }
19 | }
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | // textField.forceSwitchingRegardlessOfTag = true
24 | self.programmaticallylocalizedLabel.text = NSLocalizedString("localize_me_please", comment: "Localize me Label in the main scene")
25 |
26 | self.labelWithFont.updateFont()
27 |
28 | let identifiers : NSArray = NSLocale.availableLocaleIdentifiers as NSArray
29 | let locale = NSLocale(localeIdentifier: "en_US")
30 | let list = NSMutableString()
31 | for identifier in identifiers {
32 | let name = locale.displayName(forKey: NSLocale.Key.identifier, value: identifier)!
33 | list.append("\(identifier)\t\(name)\n")
34 | }
35 | if #available(iOS 13.0, *) {
36 | labelWithFont.isUserInteractionEnabled = true
37 | let interaction = UIContextMenuInteraction(delegate: self)
38 | labelWithFont.addInteraction(interaction)
39 |
40 | } else {
41 | // Fallback on earlier versions
42 | }
43 | self.programmaticallylocalizedLabel.text = Locale.current.identifier
44 | // let view = UIView()
45 | // view.frame = CGRect(origin: .zero, size: CGSize(width: 100, height: 400))
46 | // view.backgroundColor = .red
47 | // print("current local", Locale.current.identifier)
48 | // textField.inputView = view
49 | NotificationCenter.default.addObserver(self, selector: #selector(inputModeDidChange), name: UITextInputMode.currentInputModeDidChangeNotification, object: nil)
50 | }
51 |
52 | @objc func inputModeDidChange(_ notification: Notification) {
53 |
54 | // if let language = self.textInputMode?.primaryLanguage, MOLHLanguage.isRTLLanguage(language: language) {
55 | // textField.textAlignment = .right
56 | // } else {
57 | // textField.textAlignment = .left
58 | // }
59 | }
60 |
61 | @IBAction func switchTheLanguage(_ sender: UIButton) {
62 | MOLH.setLanguageTo(MOLHLanguage.currentAppleLanguage() == "en" ? "ar" : "en")
63 | MOLH.reset(transition: .transitionCrossDissolve, duration: 0.25)
64 | }
65 |
66 | @IBAction func didEnd(_ sender: UITextField) {
67 | sender.resignFirstResponder()
68 | }
69 |
70 | @IBAction func end(_ sender: UITextField) {
71 | sender.resignFirstResponder()
72 | }
73 |
74 |
75 |
76 |
77 | // override var textInputMode: UITextInputMode?{
78 | // print("Total number of keyboards. : \(UITextInputMode.activeInputModes.count)")
79 | //
80 | // for keyboardInputModes in UITextInputMode.activeInputModes {
81 | // if let language = keyboardInputModes.primaryLanguage {
82 | // if language == "ar" {
83 | // print("success")
84 | // return keyboardInputModes;
85 | // }
86 | // }
87 | // }
88 | //
89 | // print("failed")
90 | // return super.textInputMode;
91 | // }
92 | }
93 |
94 | //extension UIResponder {
95 | // open var textInputMode: UITextInputMode? {
96 | // CustomTextInput()
97 | // }
98 | //}
99 |
100 | class CustomTextInput: UITextInputMode {
101 | override var primaryLanguage: String? {
102 | return "fr"
103 | }
104 | }
105 |
106 | extension UIViewController {
107 | @objc open override var textInputMode: UITextInputMode? {
108 | CustomTextInput()
109 | }
110 | }
111 |
112 | final class TextView: MOLHTextField {
113 | // private var preferredTextInputModePrimaryLanguage: String? = "en"
114 | //
115 | // /**
116 | // Use given primary language for the preferred text input mode when next time text view becomes first responder.
117 | // - Parameters:
118 | // - primaryLanguage: `String` represents a primary language for the preferred text input mode. Use `"emoji"` to use Emoji keyboard.
119 | // */
120 | // func usePreferredTextInputModePrimaryLanguage(_ primaryLanguage: String) {
121 | // preferredTextInputModePrimaryLanguage = primaryLanguage
122 | // }
123 | //
124 | // /**
125 | // # UIKit Bug Workaround
126 | // - Confirmed on iOS 13.0 to iOS 13.3.
127 | // - Fixed on iOS 13.4.
128 | // `textInputMode` override is completely ignored on these version of iOS 13 due to bug in `-[UIKeyboardImpl recomputeActiveInputModesWithExtensions:allowNonLinguisticInputModes:]`,
129 | // which has a flipped condition check, which doesn't always call `-[UIKeyboardImpl setInputMode:userInitiated:]`.
130 | // To workaround this behavior, return non `nil` identifier from `textInputContextIdentifier` to call `-[UIKeyboardImpl setInputMode:userInitiated:]` from
131 | // `-[UIKeyboardInputModeController _trackInputModeIfNecessary:]` and bypass `-[UIKeyboardImpl recomputeActiveInputModesWithExtensions:allowNonLinguisticInputModes:]` call.
132 | // Also need to clean up text input context identifier once it’s used for the bug workaround.
133 | // - See also:
134 | // - `becomeFirstResponder()`
135 | // - `textInputContextIdentifier`
136 | // - `textInputMode`
137 | // */
138 | // private let shouldWorkaroundTextInputModeBug: Bool = {
139 | // // iOS 13.0 to iOS 13.3
140 | // if #available(iOS 13.0, *) {
141 | // if #available(iOS 13.4, *) {
142 | // return false
143 | // } else {
144 | // return true
145 | // }
146 | // }
147 | // return false
148 | // }()
149 | //
150 | // private let preferredTextInputModeContextIdentifier = ".preferredTextInputModeContextIdentifier"
151 | //
152 | // override func becomeFirstResponder() -> Bool {
153 | // let result = super.becomeFirstResponder()
154 | // if result {
155 | // if shouldWorkaroundTextInputModeBug {
156 | // UIResponder.clearTextInputContextIdentifier(preferredTextInputModeContextIdentifier)
157 | // }
158 | // preferredTextInputModePrimaryLanguage = "en"
159 | // }
160 | // return result
161 | // }
162 | //
163 | // override var textInputContextIdentifier: String? {
164 | // if shouldWorkaroundTextInputModeBug, preferredTextInputModePrimaryLanguage != nil {
165 | // return preferredTextInputModeContextIdentifier
166 | // }
167 | //
168 | // return super.textInputContextIdentifier
169 | // }
170 | //
171 | // override var textInputMode: UITextInputMode? {
172 | // if
173 | // let inputMode = UITextInputMode.activeInputModes.first(where: { $0.primaryLanguage?.contains("en") ?? false }) {
174 | // return inputMode
175 | // }
176 | //
177 | // return super.textInputMode
178 | // }
179 | }
180 |
181 | extension ViewController: UIContextMenuInteractionDelegate {
182 | @available(iOS 13.0, *)
183 | func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
184 |
185 | let identifier = "\(location.debugDescription)" as NSString
186 |
187 | let info = UIAction(
188 | title: "ارابيم",
189 | image: UIImage(systemName: "info.circle")) { _ in
190 | }
191 | let mute = UIAction(
192 | title: "L10n.mute",
193 | image: UIImage(systemName: "speaker.slash")) { _ in
194 | //self.showAlert("Error", message: "Implement mute action", handler: nil)
195 | }
196 |
197 | let delete = UIAction(
198 | title: "زيايل",
199 | image: UIImage(systemName: "trash")) { _ in
200 |
201 | }
202 |
203 | let audioCall = UIAction(
204 | title: "نمستي رخه",
205 | image: UIImage(systemName: "phone")) { _ in
206 | }
207 |
208 | let videoCall = UIAction(
209 | title: "L10n.videoCall",
210 | image: UIImage(systemName: "video")) { _ in
211 | }
212 |
213 | _ = UIAction(
214 | title: "L10n.exitGroup",
215 | image: UIImage(systemName: "person.3")) { _ in
216 | }
217 |
218 | var menu = UIMenu()
219 |
220 | menu = UIMenu(title: "", children: [info, mute, delete, audioCall, videoCall])
221 |
222 |
223 | return UIContextMenuConfiguration(
224 | identifier: identifier,
225 | previewProvider: nil) { _ in
226 | return menu
227 | }
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/molhWithMultipleScenese/molhWithMultipleScenese.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | ECC09DC224544C5500A7ED48 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09DC124544C5500A7ED48 /* AppDelegate.swift */; };
11 | ECC09DC424544C5500A7ED48 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09DC324544C5500A7ED48 /* SceneDelegate.swift */; };
12 | ECC09DC624544C5500A7ED48 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09DC524544C5500A7ED48 /* ViewController.swift */; };
13 | ECC09DC924544C5500A7ED48 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ECC09DC724544C5500A7ED48 /* Main.storyboard */; };
14 | ECC09DCB24544C5800A7ED48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECC09DCA24544C5800A7ED48 /* Assets.xcassets */; };
15 | ECC09DCE24544C5800A7ED48 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ECC09DCC24544C5800A7ED48 /* LaunchScreen.storyboard */; };
16 | ECC09E132454876600A7ED48 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ECC09E152454876600A7ED48 /* Localizable.strings */; };
17 | ECC09E1D2454B26900A7ED48 /* MOLHLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09E182454B26900A7ED48 /* MOLHLanguage.swift */; };
18 | ECC09E1E2454B26900A7ED48 /* MOLH.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09E192454B26900A7ED48 /* MOLH.swift */; };
19 | ECC09E1F2454B26900A7ED48 /* MOLHSizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09E1A2454B26900A7ED48 /* MOLHSizable.swift */; };
20 | ECC09E202454B26900A7ED48 /* MOLHFontLocalizableViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09E1B2454B26900A7ED48 /* MOLHFontLocalizableViews.swift */; };
21 | ECC09E212454B26900A7ED48 /* MOLHFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC09E1C2454B26900A7ED48 /* MOLHFont.swift */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | ECC09DBE24544C5500A7ED48 /* molhWithMultipleScenese.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = molhWithMultipleScenese.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | ECC09DC124544C5500A7ED48 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
27 | ECC09DC324544C5500A7ED48 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
28 | ECC09DC524544C5500A7ED48 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
29 | ECC09DC824544C5500A7ED48 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
30 | ECC09DCA24544C5800A7ED48 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
31 | ECC09DCD24544C5800A7ED48 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
32 | ECC09DCF24544C5800A7ED48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | ECC09DEB2454867E00A7ED48 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Main.strings; sourceTree = ""; };
34 | ECC09DEC2454867E00A7ED48 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LaunchScreen.strings; sourceTree = ""; };
35 | ECC09E142454876600A7ED48 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
36 | ECC09E162454876A00A7ED48 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; };
37 | ECC09E182454B26900A7ED48 /* MOLHLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MOLHLanguage.swift; sourceTree = ""; };
38 | ECC09E192454B26900A7ED48 /* MOLH.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MOLH.swift; sourceTree = ""; };
39 | ECC09E1A2454B26900A7ED48 /* MOLHSizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MOLHSizable.swift; sourceTree = ""; };
40 | ECC09E1B2454B26900A7ED48 /* MOLHFontLocalizableViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MOLHFontLocalizableViews.swift; sourceTree = ""; };
41 | ECC09E1C2454B26900A7ED48 /* MOLHFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MOLHFont.swift; sourceTree = ""; };
42 | /* End PBXFileReference section */
43 |
44 | /* Begin PBXFrameworksBuildPhase section */
45 | ECC09DBB24544C5500A7ED48 /* Frameworks */ = {
46 | isa = PBXFrameworksBuildPhase;
47 | buildActionMask = 2147483647;
48 | files = (
49 | );
50 | runOnlyForDeploymentPostprocessing = 0;
51 | };
52 | /* End PBXFrameworksBuildPhase section */
53 |
54 | /* Begin PBXGroup section */
55 | ECC09DB524544C5500A7ED48 = {
56 | isa = PBXGroup;
57 | children = (
58 | ECC09DC024544C5500A7ED48 /* molhWithMultipleScenese */,
59 | ECC09DBF24544C5500A7ED48 /* Products */,
60 | );
61 | sourceTree = "";
62 | };
63 | ECC09DBF24544C5500A7ED48 /* Products */ = {
64 | isa = PBXGroup;
65 | children = (
66 | ECC09DBE24544C5500A7ED48 /* molhWithMultipleScenese.app */,
67 | );
68 | name = Products;
69 | sourceTree = "";
70 | };
71 | ECC09DC024544C5500A7ED48 /* molhWithMultipleScenese */ = {
72 | isa = PBXGroup;
73 | children = (
74 | ECC09DC124544C5500A7ED48 /* AppDelegate.swift */,
75 | ECC09DC324544C5500A7ED48 /* SceneDelegate.swift */,
76 | ECC09DC524544C5500A7ED48 /* ViewController.swift */,
77 | ECC09E172454B26900A7ED48 /* MOLH */,
78 | ECC09E152454876600A7ED48 /* Localizable.strings */,
79 | ECC09DC724544C5500A7ED48 /* Main.storyboard */,
80 | ECC09DCA24544C5800A7ED48 /* Assets.xcassets */,
81 | ECC09DCC24544C5800A7ED48 /* LaunchScreen.storyboard */,
82 | ECC09DCF24544C5800A7ED48 /* Info.plist */,
83 | );
84 | path = molhWithMultipleScenese;
85 | sourceTree = "";
86 | };
87 | ECC09E172454B26900A7ED48 /* MOLH */ = {
88 | isa = PBXGroup;
89 | children = (
90 | ECC09E182454B26900A7ED48 /* MOLHLanguage.swift */,
91 | ECC09E192454B26900A7ED48 /* MOLH.swift */,
92 | ECC09E1A2454B26900A7ED48 /* MOLHSizable.swift */,
93 | ECC09E1B2454B26900A7ED48 /* MOLHFontLocalizableViews.swift */,
94 | ECC09E1C2454B26900A7ED48 /* MOLHFont.swift */,
95 | );
96 | name = MOLH;
97 | path = ../../Sources/MOLH;
98 | sourceTree = "";
99 | };
100 | /* End PBXGroup section */
101 |
102 | /* Begin PBXNativeTarget section */
103 | ECC09DBD24544C5500A7ED48 /* molhWithMultipleScenese */ = {
104 | isa = PBXNativeTarget;
105 | buildConfigurationList = ECC09DD224544C5800A7ED48 /* Build configuration list for PBXNativeTarget "molhWithMultipleScenese" */;
106 | buildPhases = (
107 | ECC09DBA24544C5500A7ED48 /* Sources */,
108 | ECC09DBB24544C5500A7ED48 /* Frameworks */,
109 | ECC09DBC24544C5500A7ED48 /* Resources */,
110 | );
111 | buildRules = (
112 | );
113 | dependencies = (
114 | );
115 | name = molhWithMultipleScenese;
116 | productName = molhWithMultipleScenese;
117 | productReference = ECC09DBE24544C5500A7ED48 /* molhWithMultipleScenese.app */;
118 | productType = "com.apple.product-type.application";
119 | };
120 | /* End PBXNativeTarget section */
121 |
122 | /* Begin PBXProject section */
123 | ECC09DB624544C5500A7ED48 /* Project object */ = {
124 | isa = PBXProject;
125 | attributes = {
126 | LastSwiftUpdateCheck = 1140;
127 | LastUpgradeCheck = 1140;
128 | ORGANIZATIONNAME = moath;
129 | TargetAttributes = {
130 | ECC09DBD24544C5500A7ED48 = {
131 | CreatedOnToolsVersion = 11.4.1;
132 | };
133 | };
134 | };
135 | buildConfigurationList = ECC09DB924544C5500A7ED48 /* Build configuration list for PBXProject "molhWithMultipleScenese" */;
136 | compatibilityVersion = "Xcode 9.3";
137 | developmentRegion = en;
138 | hasScannedForEncodings = 0;
139 | knownRegions = (
140 | en,
141 | Base,
142 | ar,
143 | ur,
144 | "ckb-IR",
145 | "agq-CM",
146 | "ckb-IQ",
147 | "he-IL",
148 | );
149 | mainGroup = ECC09DB524544C5500A7ED48;
150 | productRefGroup = ECC09DBF24544C5500A7ED48 /* Products */;
151 | projectDirPath = "";
152 | projectRoot = "";
153 | targets = (
154 | ECC09DBD24544C5500A7ED48 /* molhWithMultipleScenese */,
155 | );
156 | };
157 | /* End PBXProject section */
158 |
159 | /* Begin PBXResourcesBuildPhase section */
160 | ECC09DBC24544C5500A7ED48 /* Resources */ = {
161 | isa = PBXResourcesBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | ECC09DCE24544C5800A7ED48 /* LaunchScreen.storyboard in Resources */,
165 | ECC09E132454876600A7ED48 /* Localizable.strings in Resources */,
166 | ECC09DCB24544C5800A7ED48 /* Assets.xcassets in Resources */,
167 | ECC09DC924544C5500A7ED48 /* Main.storyboard in Resources */,
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | };
171 | /* End PBXResourcesBuildPhase section */
172 |
173 | /* Begin PBXSourcesBuildPhase section */
174 | ECC09DBA24544C5500A7ED48 /* Sources */ = {
175 | isa = PBXSourcesBuildPhase;
176 | buildActionMask = 2147483647;
177 | files = (
178 | ECC09E212454B26900A7ED48 /* MOLHFont.swift in Sources */,
179 | ECC09E1F2454B26900A7ED48 /* MOLHSizable.swift in Sources */,
180 | ECC09DC624544C5500A7ED48 /* ViewController.swift in Sources */,
181 | ECC09E1E2454B26900A7ED48 /* MOLH.swift in Sources */,
182 | ECC09E1D2454B26900A7ED48 /* MOLHLanguage.swift in Sources */,
183 | ECC09DC224544C5500A7ED48 /* AppDelegate.swift in Sources */,
184 | ECC09E202454B26900A7ED48 /* MOLHFontLocalizableViews.swift in Sources */,
185 | ECC09DC424544C5500A7ED48 /* SceneDelegate.swift in Sources */,
186 | );
187 | runOnlyForDeploymentPostprocessing = 0;
188 | };
189 | /* End PBXSourcesBuildPhase section */
190 |
191 | /* Begin PBXVariantGroup section */
192 | ECC09DC724544C5500A7ED48 /* Main.storyboard */ = {
193 | isa = PBXVariantGroup;
194 | children = (
195 | ECC09DC824544C5500A7ED48 /* Base */,
196 | ECC09DEB2454867E00A7ED48 /* ar */,
197 | );
198 | name = Main.storyboard;
199 | sourceTree = "";
200 | };
201 | ECC09DCC24544C5800A7ED48 /* LaunchScreen.storyboard */ = {
202 | isa = PBXVariantGroup;
203 | children = (
204 | ECC09DCD24544C5800A7ED48 /* Base */,
205 | ECC09DEC2454867E00A7ED48 /* ar */,
206 | );
207 | name = LaunchScreen.storyboard;
208 | sourceTree = "";
209 | };
210 | ECC09E152454876600A7ED48 /* Localizable.strings */ = {
211 | isa = PBXVariantGroup;
212 | children = (
213 | ECC09E142454876600A7ED48 /* en */,
214 | ECC09E162454876A00A7ED48 /* ar */,
215 | );
216 | name = Localizable.strings;
217 | sourceTree = "";
218 | };
219 | /* End PBXVariantGroup section */
220 |
221 | /* Begin XCBuildConfiguration section */
222 | ECC09DD024544C5800A7ED48 /* Debug */ = {
223 | isa = XCBuildConfiguration;
224 | buildSettings = {
225 | ALWAYS_SEARCH_USER_PATHS = NO;
226 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
227 | CLANG_ANALYZER_NONNULL = YES;
228 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
230 | CLANG_CXX_LIBRARY = "libc++";
231 | CLANG_ENABLE_MODULES = YES;
232 | CLANG_ENABLE_OBJC_ARC = YES;
233 | CLANG_ENABLE_OBJC_WEAK = YES;
234 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
235 | CLANG_WARN_BOOL_CONVERSION = YES;
236 | CLANG_WARN_COMMA = YES;
237 | CLANG_WARN_CONSTANT_CONVERSION = YES;
238 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
239 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
240 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
241 | CLANG_WARN_EMPTY_BODY = YES;
242 | CLANG_WARN_ENUM_CONVERSION = YES;
243 | CLANG_WARN_INFINITE_RECURSION = YES;
244 | CLANG_WARN_INT_CONVERSION = YES;
245 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
246 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
247 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
248 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
249 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
250 | CLANG_WARN_STRICT_PROTOTYPES = YES;
251 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
252 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
253 | CLANG_WARN_UNREACHABLE_CODE = YES;
254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
255 | COPY_PHASE_STRIP = NO;
256 | DEBUG_INFORMATION_FORMAT = dwarf;
257 | ENABLE_STRICT_OBJC_MSGSEND = YES;
258 | ENABLE_TESTABILITY = YES;
259 | GCC_C_LANGUAGE_STANDARD = gnu11;
260 | GCC_DYNAMIC_NO_PIC = NO;
261 | GCC_NO_COMMON_BLOCKS = YES;
262 | GCC_OPTIMIZATION_LEVEL = 0;
263 | GCC_PREPROCESSOR_DEFINITIONS = (
264 | "DEBUG=1",
265 | "$(inherited)",
266 | );
267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
269 | GCC_WARN_UNDECLARED_SELECTOR = YES;
270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
271 | GCC_WARN_UNUSED_FUNCTION = YES;
272 | GCC_WARN_UNUSED_VARIABLE = YES;
273 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
274 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
275 | MTL_FAST_MATH = YES;
276 | ONLY_ACTIVE_ARCH = YES;
277 | SDKROOT = iphoneos;
278 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
279 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
280 | };
281 | name = Debug;
282 | };
283 | ECC09DD124544C5800A7ED48 /* Release */ = {
284 | isa = XCBuildConfiguration;
285 | buildSettings = {
286 | ALWAYS_SEARCH_USER_PATHS = NO;
287 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
288 | CLANG_ANALYZER_NONNULL = YES;
289 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
290 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
291 | CLANG_CXX_LIBRARY = "libc++";
292 | CLANG_ENABLE_MODULES = YES;
293 | CLANG_ENABLE_OBJC_ARC = YES;
294 | CLANG_ENABLE_OBJC_WEAK = YES;
295 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
296 | CLANG_WARN_BOOL_CONVERSION = YES;
297 | CLANG_WARN_COMMA = YES;
298 | CLANG_WARN_CONSTANT_CONVERSION = YES;
299 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
301 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
302 | CLANG_WARN_EMPTY_BODY = YES;
303 | CLANG_WARN_ENUM_CONVERSION = YES;
304 | CLANG_WARN_INFINITE_RECURSION = YES;
305 | CLANG_WARN_INT_CONVERSION = YES;
306 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
307 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
308 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
310 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
311 | CLANG_WARN_STRICT_PROTOTYPES = YES;
312 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
313 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
314 | CLANG_WARN_UNREACHABLE_CODE = YES;
315 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
316 | COPY_PHASE_STRIP = NO;
317 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
318 | ENABLE_NS_ASSERTIONS = NO;
319 | ENABLE_STRICT_OBJC_MSGSEND = YES;
320 | GCC_C_LANGUAGE_STANDARD = gnu11;
321 | GCC_NO_COMMON_BLOCKS = YES;
322 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
323 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
324 | GCC_WARN_UNDECLARED_SELECTOR = YES;
325 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
326 | GCC_WARN_UNUSED_FUNCTION = YES;
327 | GCC_WARN_UNUSED_VARIABLE = YES;
328 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
329 | MTL_ENABLE_DEBUG_INFO = NO;
330 | MTL_FAST_MATH = YES;
331 | SDKROOT = iphoneos;
332 | SWIFT_COMPILATION_MODE = wholemodule;
333 | SWIFT_OPTIMIZATION_LEVEL = "-O";
334 | VALIDATE_PRODUCT = YES;
335 | };
336 | name = Release;
337 | };
338 | ECC09DD324544C5800A7ED48 /* Debug */ = {
339 | isa = XCBuildConfiguration;
340 | buildSettings = {
341 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
342 | CODE_SIGN_STYLE = Automatic;
343 | DEVELOPMENT_TEAM = 698J8YQ47A;
344 | INFOPLIST_FILE = molhWithMultipleScenese/Info.plist;
345 | IPHONEOS_DEPLOYMENT_TARGET = 11.4;
346 | LD_RUNPATH_SEARCH_PATHS = (
347 | "$(inherited)",
348 | "@executable_path/Frameworks",
349 | );
350 | PRODUCT_BUNDLE_IDENTIFIER = com.moath.molhWithMultipleScenese;
351 | PRODUCT_NAME = "$(TARGET_NAME)";
352 | SWIFT_VERSION = 5.0;
353 | TARGETED_DEVICE_FAMILY = "1,2";
354 | };
355 | name = Debug;
356 | };
357 | ECC09DD424544C5800A7ED48 /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
361 | CODE_SIGN_STYLE = Automatic;
362 | DEVELOPMENT_TEAM = 698J8YQ47A;
363 | INFOPLIST_FILE = molhWithMultipleScenese/Info.plist;
364 | IPHONEOS_DEPLOYMENT_TARGET = 11.4;
365 | LD_RUNPATH_SEARCH_PATHS = (
366 | "$(inherited)",
367 | "@executable_path/Frameworks",
368 | );
369 | PRODUCT_BUNDLE_IDENTIFIER = com.moath.molhWithMultipleScenese;
370 | PRODUCT_NAME = "$(TARGET_NAME)";
371 | SWIFT_VERSION = 5.0;
372 | TARGETED_DEVICE_FAMILY = "1,2";
373 | };
374 | name = Release;
375 | };
376 | /* End XCBuildConfiguration section */
377 |
378 | /* Begin XCConfigurationList section */
379 | ECC09DB924544C5500A7ED48 /* Build configuration list for PBXProject "molhWithMultipleScenese" */ = {
380 | isa = XCConfigurationList;
381 | buildConfigurations = (
382 | ECC09DD024544C5800A7ED48 /* Debug */,
383 | ECC09DD124544C5800A7ED48 /* Release */,
384 | );
385 | defaultConfigurationIsVisible = 0;
386 | defaultConfigurationName = Release;
387 | };
388 | ECC09DD224544C5800A7ED48 /* Build configuration list for PBXNativeTarget "molhWithMultipleScenese" */ = {
389 | isa = XCConfigurationList;
390 | buildConfigurations = (
391 | ECC09DD324544C5800A7ED48 /* Debug */,
392 | ECC09DD424544C5800A7ED48 /* Release */,
393 | );
394 | defaultConfigurationIsVisible = 0;
395 | defaultConfigurationName = Release;
396 | };
397 | /* End XCConfigurationList section */
398 | };
399 | rootObject = ECC09DB624544C5500A7ED48 /* Project object */;
400 | }
401 |
--------------------------------------------------------------------------------
/Sources/MOLH/MOLH.swift:
--------------------------------------------------------------------------------
1 | // Moath Othman
2 | // MIT license
3 |
4 | import Foundation
5 | import UIKit
6 |
7 | protocol LayoutSwizzlable: NSObjectProtocol {
8 | func handleSwitching(forceSwitchingRegardlessOfTag: Bool)
9 | }
10 |
11 | protocol Taggable: NSObjectProtocol {
12 | var tag: Int {get set}
13 | }
14 |
15 | protocol TextAlignmented: NSObjectProtocol {
16 | var textAlignment: NSTextAlignment {get set}
17 | }
18 |
19 | extension LayoutSwizzlable where Self: TextAlignmented & Taggable {
20 | func handleSwitching(forceSwitchingRegardlessOfTag: Bool) {
21 | if self.tag < MOLH.shared.maximumLocalizableTag + 1 || forceSwitchingRegardlessOfTag , textAlignment != .center {
22 | if MOLHLanguage.isRTLLanguage() {
23 | if self.textAlignment == .right { return }
24 | self.textAlignment = .right
25 | } else {
26 | if self.textAlignment == .left { return }
27 | self.textAlignment = .left
28 | }
29 | }
30 | }
31 | }
32 |
33 | /// the type of text view , field , label
34 | typealias TextViewType = Taggable & LayoutSwizzlable & TextAlignmented
35 |
36 | /// Localize function
37 | public protocol MOLHLocalizable {
38 | func localize()
39 | }
40 |
41 | /// reset bundles
42 | public protocol MOLHResetable {
43 | func reset()
44 | }
45 |
46 | @available(iOS 13.0, *)
47 | public protocol MOLHSceneResetable {
48 | func reset(scene: UIScene)
49 | }
50 |
51 | open class MOLHViewController : UIViewController {
52 | open override func viewDidLoad() {
53 | super.viewDidLoad()
54 | if self is MOLHLocalizable {
55 | (self as! MOLHLocalizable).localize()
56 | }
57 | }
58 | }
59 |
60 | open class MOLHTableViewController : UITableViewController {
61 | open override func viewDidLoad() {
62 | super.viewDidLoad()
63 | if self is MOLHLocalizable {
64 | (self as! MOLHLocalizable).localize()
65 | }
66 | }
67 | }
68 |
69 | open class MOLHView : UIView {
70 | open override func layoutSubviews() {
71 | super.layoutSubviews()
72 |
73 | if self is MOLHLocalizable {
74 | (self as! MOLHLocalizable).localize()
75 | }
76 |
77 | if self is MOLHFontable {
78 | (self as! MOLHFontable).updateFont()
79 | }
80 | }
81 | }
82 |
83 | open class MOLH {
84 | fileprivate struct Shared {
85 | static let shared = MOLH()
86 | }
87 |
88 | /// which bundle to fallback to if the current language has no bundle
89 | open var fallbackLocale = "Base"
90 |
91 | /// Prevent MOLH()
92 | fileprivate init() {}
93 |
94 | /// shared Instance , MOLH should be accessed through this shared
95 | public static let shared = Shared.shared
96 |
97 | /**
98 | @description
99 | * set the maximum tag where a UIView subclass Deemed Localizable
100 | * if view Tag property is bigger than this number the view will not be flipped
101 | */
102 | open var maximumLocalizableTag: Int = -1 {
103 | didSet {
104 | assert(maximumLocalizableTag <= -1, "Tag should be less than or equal -1 , since 0 will corrupt UIKit-Made UIs e.g. UIAlertView/Share...")
105 | }
106 | }
107 |
108 | /**
109 | @description
110 | * set special keywords "Keys" that handled by external frameworks to be localized locally
111 | */
112 | public var specialKeyWords: [String] = []
113 |
114 | /**
115 | Activate Localization Helper
116 |
117 | **@param** swizzleExtensions Bool if you want to use run time swizzle with all Views like uilabel, default is false...
118 |
119 | **@note** swizzling extension could lead to issues if you are swizzling your UIViews **layoutSubviews** method from another place
120 | */
121 | open func activate(_ swizzleExtensions: Bool = false) {
122 | swizzle(class: Bundle.self, sel: #selector(Bundle.localizedString(forKey:value:table:)), override: #selector(Bundle.specialLocalizedStringForKey(_:value:table:)))
123 | swizzle(class:UIApplication.self, sel: #selector(getter: UIApplication.userInterfaceLayoutDirection), override: #selector(getter: UIApplication.cstm_userInterfaceLayoutDirection))
124 |
125 | if swizzleExtensions {
126 | swizzle(class:UIViewController.self, sel: #selector(UIViewController.viewDidLayoutSubviews), override: #selector(UIViewController.mirroringviewDidLoad))
127 | swizzle(class:UIControl.self, sel: #selector(UIControl.awakeFromNib), override: #selector(UIControl.cstmlayoutSubviews))
128 | swizzle(class:UITextField.self, sel: #selector(UITextField.layoutSubviews), override: #selector(UITextField.cstmlayoutSubviews))
129 | swizzle(class:UITextView.self, sel: #selector(UITextView.layoutSubviews), override: #selector(UITextView.cstmlayoutSubviews))
130 | swizzle(class:UILabel.self, sel: #selector(UILabel.layoutSubviews), override: #selector(UILabel.cstmlayoutSubviews))
131 | }
132 | }
133 |
134 | /// Set Language , Language parameter string identify the language e.x. en, ar,fr ...
135 | open class func setLanguageTo(_ language: String) {
136 | MOLHLanguage.setAppleLanguageTo(language)
137 | if MOLHLanguage.isRTLLanguage() {
138 | UIView.appearance().semanticContentAttribute = .forceRightToLeft
139 | UIButton.appearance().semanticContentAttribute = .forceRightToLeft
140 | UITextView.appearance().semanticContentAttribute = .forceRightToLeft
141 | UITextField.appearance().semanticContentAttribute = .forceRightToLeft
142 | UINavigationBar.appearance().semanticContentAttribute = .forceRightToLeft
143 | UITabBar.appearance().semanticContentAttribute = .forceRightToLeft
144 | UISearchBar.appearance().semanticContentAttribute = .forceRightToLeft
145 | UILabel.appearance().semanticContentAttribute = .forceRightToLeft
146 | } else {
147 | UIView.appearance().semanticContentAttribute = .forceLeftToRight
148 | UIButton.appearance().semanticContentAttribute = .forceLeftToRight
149 | UITextView.appearance().semanticContentAttribute = .forceLeftToRight
150 | UITextField.appearance().semanticContentAttribute = .forceLeftToRight
151 | UINavigationBar.appearance().semanticContentAttribute = .forceLeftToRight
152 | UITabBar.appearance().semanticContentAttribute = .forceLeftToRight
153 | UISearchBar.appearance().semanticContentAttribute = .forceLeftToRight
154 | UILabel.appearance().semanticContentAttribute = .forceLeftToRight
155 | }
156 | }
157 |
158 | /**
159 | reset app which will perform transition and call reset on appdelegate if it's MOLHResetable
160 | */
161 | open class func reset(duration: Float = 0.5) {
162 | var transition = UIView.AnimationOptions.transitionFlipFromRight
163 | if !MOLHLanguage.isRTLLanguage() {
164 | transition = .transitionFlipFromLeft
165 | }
166 | reset(transition: transition, duration: duration)
167 | }
168 |
169 | open class func reset(transition: UIView.AnimationOptions, duration: Float = 0.5) {
170 |
171 | func resetWhenNoScenesAvailable() {
172 | if let delegate = UIApplication.shared.delegate {
173 | if delegate is MOLHResetable {
174 | (delegate as!MOLHResetable).reset()
175 | }
176 | UIView.transition(with: ((delegate.window)!)!, duration: TimeInterval(duration), options: transition, animations: {})
177 | }
178 | }
179 |
180 | if #available(iOS 13.0, *) {
181 | if let window = UIApplication.shared.delegate?.window, window != nil {
182 | resetWhenNoScenesAvailable()
183 | } else {
184 | for scene in UIApplication.shared.connectedScenes {
185 | (scene.delegate as? MOLHSceneResetable)?.reset(scene: scene)
186 | }
187 | }
188 | } else {
189 | resetWhenNoScenesAvailable()
190 | }
191 | }
192 | }
193 |
194 | extension UIApplication {
195 | @objc var cstm_userInterfaceLayoutDirection : UIUserInterfaceLayoutDirection {
196 | get {
197 | var direction = UIUserInterfaceLayoutDirection.leftToRight
198 | if MOLHLanguage.isRTLLanguage() {
199 | direction = .rightToLeft
200 | }
201 | return direction
202 | }
203 | }
204 | }
205 |
206 | extension Bundle {
207 | @objc func specialLocalizedStringForKey(_ key: String, value: String?, table tableName: String?) -> String {
208 | // check if its the main bundle then if the bundle of the current language is available
209 | // then try without locale
210 | // if not go back to base
211 | let translate = { (tableName: String?) -> String in
212 | let currentLanguage = MOLHLanguage.currentLocaleIdentifier() // with locale
213 | let languageWithoutLocale = MOLHLanguage.currentAppleLanguage() // without locale
214 | var bundle = Bundle();
215 | // normal case where the lang with locale working
216 | if let _path = Bundle.main.path(forResource: currentLanguage, ofType: "lproj") {
217 | bundle = Bundle(path: _path)!
218 | } // en case when its working wihout locale
219 | else if let _path = Bundle.main.path(forResource: languageWithoutLocale, ofType: "lproj") {
220 | bundle = Bundle(path: _path)!
221 | } // current locale not exist , so we fallback
222 | else if let _path = Bundle.main.path(forResource: MOLH.shared.fallbackLocale, ofType: "lproj") {
223 | bundle = Bundle(path: _path)!
224 | }
225 | return (bundle.specialLocalizedStringForKey(key, value: value, table: tableName))
226 | }
227 | // normal case
228 | if self == Bundle.main {
229 | return translate(tableName)
230 | } // case when the external frameworks has no locale proberty so you have to handle switching yourself
231 | else if MOLH.shared.specialKeyWords.contains(key) {
232 | return translate("Localizable")
233 | } // let the bundle handle the locale
234 | else {
235 | return (self.specialLocalizedStringForKey(key, value: value, table: tableName))
236 | }
237 | }
238 | }
239 |
240 | extension UIImage {
241 | public func flippedImage() -> UIImage?{
242 | if let _cgImag = self.cgImage {
243 | let flippedimg = UIImage(cgImage: _cgImag, scale:self.scale , orientation: UIImage.Orientation.upMirrored)
244 | return flippedimg
245 | }
246 | return nil
247 | }
248 |
249 | public func flipIfNeeded() -> UIImage? {
250 | if MOLHLanguage.isRTLLanguage() {
251 | return self.flippedImage()
252 | }
253 | return self
254 | }
255 | }
256 |
257 | extension UIViewController {
258 |
259 | @objc func mirroringviewDidLoad() {
260 | mirroringviewDidLoad()
261 | if UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft {
262 | loopThroughSubViewAndFlipTheImageIfItsNeeded(self.view.subviews)
263 | }
264 | // Do any additional setup after loading the view.
265 | }
266 |
267 | /**
268 | Loop through subviews recursivley ,finding any image , uibutton image,uislider image that needs to be flipped
269 | , meaning its tagged less than maximumLocalizableTag and flip it
270 |
271 | @param the view subviews to start with.
272 |
273 | @note note that we suppose that the original is left to right image by default , an image is only flipped if the
274 | currentLanguage is right to left
275 |
276 | @return nothing
277 | */
278 | func loopThroughSubViewAndFlipTheImageIfItsNeeded(_ subviews: [UIView]) {
279 |
280 | if subviews.count > 0 && MOLHLanguage.isRTLLanguage() {
281 | for subView in subviews where subView.tag <= MOLH.shared.maximumLocalizableTag {
282 | // Flip UIImageView
283 | if subView.isKind(of: UIImageView.self) {
284 | let toRightArrow = subView as! UIImageView
285 | toRightArrow.image = toRightArrow.image?.flipIfNeeded()
286 | }
287 | // Flip UISlider thumb image
288 | if subView.isKind(of: UISlider.self) {
289 | let toRightArrow = subView as! UISlider
290 | let _img = toRightArrow.thumbImage(for: UIControl.State())
291 | let flipped = _img?.flipIfNeeded()
292 | toRightArrow.setThumbImage(flipped, for: UIControl.State())
293 | toRightArrow.setThumbImage(flipped, for: .selected)
294 | toRightArrow.setThumbImage(flipped, for: .highlighted)
295 | }
296 | // Flip UIButton image
297 | if subView.isKind(of: UIButton.self) {
298 | let _subView = subView as! UIButton
299 | var image = _subView.image(for: UIControl.State())
300 | image = image?.flippedImage()
301 | _subView.setImage(image, for: UIControl.State())
302 | _subView.setImage(image, for: UIControl.State.selected)
303 | _subView.setImage(image, for: UIControl.State.highlighted)
304 | }
305 |
306 | loopThroughSubViewAndFlipTheImageIfItsNeeded(subView.subviews)
307 | }
308 | }
309 | }
310 |
311 | }
312 |
313 | // MARK : - Extensions
314 | extension UIControl {
315 | internal func handleControlSwitching(forceSwitchingRegardlessOfTag: Bool) {
316 | if self.tag < MOLH.shared.maximumLocalizableTag + 1 || forceSwitchingRegardlessOfTag {
317 | if MOLHLanguage.isRTLLanguage() {
318 | if self.contentHorizontalAlignment == .right { return }
319 | self.contentHorizontalAlignment = .right
320 | } else {
321 | if self.contentHorizontalAlignment == .left { return }
322 | self.contentHorizontalAlignment = .left
323 | }
324 | }
325 | }
326 |
327 | @objc public func cstmlayoutSubviews() {
328 | self.cstmlayoutSubviews()
329 | handleControlSwitching(forceSwitchingRegardlessOfTag: false)
330 | }
331 | }
332 |
333 | extension UITextField: TextViewType {
334 | public override func cstmlayoutSubviews() {
335 | self.cstmlayoutSubviews()
336 | handleSwitching(forceSwitchingRegardlessOfTag: false)
337 | handleControlSwitching(forceSwitchingRegardlessOfTag: false)
338 | }
339 | }
340 |
341 | extension UITextView: TextViewType {
342 | @objc public func cstmlayoutSubviews() {
343 | self.cstmlayoutSubviews()
344 | handleSwitching(forceSwitchingRegardlessOfTag: false)
345 | }
346 | }
347 |
348 | extension UILabel: TextViewType {
349 | @objc public func cstmlayoutSubviews() {
350 | self.cstmlayoutSubviews()
351 | handleSwitching(forceSwitchingRegardlessOfTag: false)
352 | }
353 | }
354 |
355 |
356 | // MARK: - SubClasses
357 | /**
358 | `MOLHControl is a UIControl Subclass`
359 |
360 | Any UIControl that wants to be localizable should be subclass of this class
361 | @auther Moath Othman
362 | */
363 | open class MOLHControl: UIControl {
364 | open var forceSwitchingRegardlessOfTag: Bool = false {
365 | didSet {
366 | handleControlSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
367 | }
368 | }
369 | override open func layoutSubviews() {
370 | super.layoutSubviews()
371 | handleControlSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
372 | }
373 | }
374 | /**
375 | MOLHLabel is a UILabel Subclass
376 | Any Label that wants to be localizable should be subclass of this class§
377 | @auther Moath Othman
378 | */
379 | open class MOLHLabel: UILabel {
380 | open var forceSwitchingRegardlessOfTag: Bool = false {
381 | didSet {
382 | handleSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
383 | }
384 | }
385 | override open func layoutSubviews() {
386 | super.layoutSubviews()
387 | handleSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
388 | }
389 | }
390 | /**
391 | MOLHTextView is a UITextView Subclass
392 | Any TextView that wants to be localizable should be subclass of this class§
393 | @auther Moath Othman
394 | */
395 | open class MOLHTextView: UITextView {
396 | open var forceSwitchingRegardlessOfTag: Bool = false {
397 | didSet {
398 | handleSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
399 | }
400 | }
401 | override open func layoutSubviews() {
402 | super.layoutSubviews()
403 | handleSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
404 | }
405 | }
406 | /**
407 | MOLHTextField is a UITextField Subclass
408 | Any TextField that wants to be localizable should be subclass of this class§
409 | @auther Moath Othman
410 | */
411 | open class MOLHTextField: UITextField {
412 | open var forceSwitchingRegardlessOfTag: Bool = false {
413 | didSet {
414 | setupForLocalization()
415 | }
416 | }
417 |
418 | public override init(frame: CGRect) {
419 | super.init(frame: frame)
420 | setupForLocalization()
421 | }
422 |
423 | public required init?(coder aDecoder: NSCoder) {
424 | super.init(coder: aDecoder)
425 | setupForLocalization()
426 | }
427 |
428 | func setupForLocalization() {
429 | handleControlSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
430 | handleSwitching(forceSwitchingRegardlessOfTag: forceSwitchingRegardlessOfTag)
431 | }
432 | }
433 |
434 | // MARK: - Utility
435 | /// Exchange the implementation of two methods for the same Class override will replace sel
436 | private func swizzle(class cls: AnyClass, sel: Selector, override: Selector) {
437 | guard let origMethod: Method = class_getInstanceMethod(cls, sel) else { return }
438 | guard let overrideMethod: Method = class_getInstanceMethod(cls, override) else { return }
439 | if (class_addMethod(cls, sel, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
440 | class_replaceMethod(cls, override, method_getImplementation(origMethod), method_getTypeEncoding(origMethod))
441 | } else {
442 | method_exchangeImplementations(origMethod, overrideMethod);
443 | }
444 | }
445 |
446 |
--------------------------------------------------------------------------------
/MOLH.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = "1";
4 | objectVersion = "46";
5 | objects = {
6 | "MOLH::MOLH" = {
7 | isa = "PBXNativeTarget";
8 | buildConfigurationList = "OBJ_27";
9 | buildPhases = (
10 | "OBJ_30",
11 | "OBJ_36"
12 | );
13 | dependencies = (
14 | );
15 | name = "MOLH";
16 | productName = "MOLH";
17 | productReference = "MOLH::MOLH::Product";
18 | productType = "com.apple.product-type.framework";
19 | };
20 | "MOLH::MOLH::Product" = {
21 | isa = "PBXFileReference";
22 | path = "MOLH.framework";
23 | sourceTree = "BUILT_PRODUCTS_DIR";
24 | };
25 | "MOLH::MOLHPackageTests::ProductTarget" = {
26 | isa = "PBXAggregateTarget";
27 | buildConfigurationList = "OBJ_44";
28 | buildPhases = (
29 | );
30 | dependencies = (
31 | "OBJ_47"
32 | );
33 | name = "MOLHPackageTests";
34 | productName = "MOLHPackageTests";
35 | };
36 | "MOLH::MOLHTests" = {
37 | isa = "PBXNativeTarget";
38 | buildConfigurationList = "OBJ_49";
39 | buildPhases = (
40 | "OBJ_52",
41 | "OBJ_55"
42 | );
43 | dependencies = (
44 | "OBJ_57"
45 | );
46 | name = "MOLHTests";
47 | productName = "MOLHTests";
48 | productReference = "MOLH::MOLHTests::Product";
49 | productType = "com.apple.product-type.bundle.unit-test";
50 | };
51 | "MOLH::MOLHTests::Product" = {
52 | isa = "PBXFileReference";
53 | path = "MOLHTests.xctest";
54 | sourceTree = "BUILT_PRODUCTS_DIR";
55 | };
56 | "MOLH::SwiftPMPackageDescription" = {
57 | isa = "PBXNativeTarget";
58 | buildConfigurationList = "OBJ_38";
59 | buildPhases = (
60 | "OBJ_41"
61 | );
62 | dependencies = (
63 | );
64 | name = "MOLHPackageDescription";
65 | productName = "MOLHPackageDescription";
66 | productType = "com.apple.product-type.framework";
67 | };
68 | "OBJ_1" = {
69 | isa = "PBXProject";
70 | attributes = {
71 | LastSwiftMigration = "9999";
72 | LastUpgradeCheck = "9999";
73 | };
74 | buildConfigurationList = "OBJ_2";
75 | compatibilityVersion = "Xcode 3.2";
76 | developmentRegion = "en";
77 | hasScannedForEncodings = "0";
78 | knownRegions = (
79 | "en"
80 | );
81 | mainGroup = "OBJ_5";
82 | productRefGroup = "OBJ_18";
83 | projectDirPath = ".";
84 | targets = (
85 | "MOLH::MOLH",
86 | "MOLH::SwiftPMPackageDescription",
87 | "MOLH::MOLHPackageTests::ProductTarget",
88 | "MOLH::MOLHTests"
89 | );
90 | };
91 | "OBJ_10" = {
92 | isa = "PBXFileReference";
93 | path = "MOLHFont.swift";
94 | sourceTree = "";
95 | };
96 | "OBJ_11" = {
97 | isa = "PBXFileReference";
98 | path = "MOLHFontLocalizableViews.swift";
99 | sourceTree = "";
100 | };
101 | "OBJ_12" = {
102 | isa = "PBXFileReference";
103 | path = "MOLHLanguage.swift";
104 | sourceTree = "";
105 | };
106 | "OBJ_13" = {
107 | isa = "PBXFileReference";
108 | path = "MOLHSizable.swift";
109 | sourceTree = "";
110 | };
111 | "OBJ_14" = {
112 | isa = "PBXGroup";
113 | children = (
114 | "OBJ_15"
115 | );
116 | name = "Tests";
117 | path = "";
118 | sourceTree = "SOURCE_ROOT";
119 | };
120 | "OBJ_15" = {
121 | isa = "PBXGroup";
122 | children = (
123 | "OBJ_16",
124 | "OBJ_17"
125 | );
126 | name = "MOLHTests";
127 | path = "Tests/MOLHTests";
128 | sourceTree = "SOURCE_ROOT";
129 | };
130 | "OBJ_16" = {
131 | isa = "PBXFileReference";
132 | path = "MOLHTests.swift";
133 | sourceTree = "";
134 | };
135 | "OBJ_17" = {
136 | isa = "PBXFileReference";
137 | path = "XCTestManifests.swift";
138 | sourceTree = "";
139 | };
140 | "OBJ_18" = {
141 | isa = "PBXGroup";
142 | children = (
143 | "MOLH::MOLHTests::Product",
144 | "MOLH::MOLH::Product"
145 | );
146 | name = "Products";
147 | path = "";
148 | sourceTree = "BUILT_PRODUCTS_DIR";
149 | };
150 | "OBJ_2" = {
151 | isa = "XCConfigurationList";
152 | buildConfigurations = (
153 | "OBJ_3",
154 | "OBJ_4"
155 | );
156 | defaultConfigurationIsVisible = "0";
157 | defaultConfigurationName = "Release";
158 | };
159 | "OBJ_21" = {
160 | isa = "PBXFileReference";
161 | path = "LocalizationHelperDemo";
162 | sourceTree = "SOURCE_ROOT";
163 | };
164 | "OBJ_22" = {
165 | isa = "PBXFileReference";
166 | path = "LICENSE";
167 | sourceTree = "";
168 | };
169 | "OBJ_23" = {
170 | isa = "PBXFileReference";
171 | path = "MOLH.podspec";
172 | sourceTree = "";
173 | };
174 | "OBJ_24" = {
175 | isa = "PBXFileReference";
176 | path = "README.md";
177 | sourceTree = "";
178 | };
179 | "OBJ_25" = {
180 | isa = "PBXFileReference";
181 | path = "post.md";
182 | sourceTree = "";
183 | };
184 | "OBJ_27" = {
185 | isa = "XCConfigurationList";
186 | buildConfigurations = (
187 | "OBJ_28",
188 | "OBJ_29"
189 | );
190 | defaultConfigurationIsVisible = "0";
191 | defaultConfigurationName = "Release";
192 | };
193 | "OBJ_28" = {
194 | isa = "XCBuildConfiguration";
195 | buildSettings = {
196 | ENABLE_TESTABILITY = "YES";
197 | FRAMEWORK_SEARCH_PATHS = (
198 | "$(inherited)",
199 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
200 | );
201 | HEADER_SEARCH_PATHS = (
202 | "$(inherited)"
203 | );
204 | INFOPLIST_FILE = "MOLH.xcodeproj/MOLH_Info.plist";
205 | IPHONEOS_DEPLOYMENT_TARGET = "10.0";
206 | LD_RUNPATH_SEARCH_PATHS = (
207 | "$(inherited)",
208 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"
209 | );
210 | MACOSX_DEPLOYMENT_TARGET = "10.10";
211 | OTHER_CFLAGS = (
212 | "$(inherited)"
213 | );
214 | OTHER_LDFLAGS = (
215 | "$(inherited)"
216 | );
217 | OTHER_SWIFT_FLAGS = (
218 | "$(inherited)"
219 | );
220 | PRODUCT_BUNDLE_IDENTIFIER = "MOLH";
221 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
222 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
223 | SKIP_INSTALL = "YES";
224 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
225 | "$(inherited)"
226 | );
227 | SWIFT_VERSION = "5.0";
228 | TARGET_NAME = "MOLH";
229 | TVOS_DEPLOYMENT_TARGET = "9.0";
230 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
231 | };
232 | name = "Debug";
233 | };
234 | "OBJ_29" = {
235 | isa = "XCBuildConfiguration";
236 | buildSettings = {
237 | ENABLE_TESTABILITY = "YES";
238 | FRAMEWORK_SEARCH_PATHS = (
239 | "$(inherited)",
240 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
241 | );
242 | HEADER_SEARCH_PATHS = (
243 | "$(inherited)"
244 | );
245 | INFOPLIST_FILE = "MOLH.xcodeproj/MOLH_Info.plist";
246 | IPHONEOS_DEPLOYMENT_TARGET = "10.0";
247 | LD_RUNPATH_SEARCH_PATHS = (
248 | "$(inherited)",
249 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"
250 | );
251 | MACOSX_DEPLOYMENT_TARGET = "10.10";
252 | OTHER_CFLAGS = (
253 | "$(inherited)"
254 | );
255 | OTHER_LDFLAGS = (
256 | "$(inherited)"
257 | );
258 | OTHER_SWIFT_FLAGS = (
259 | "$(inherited)"
260 | );
261 | PRODUCT_BUNDLE_IDENTIFIER = "MOLH";
262 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
263 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
264 | SKIP_INSTALL = "YES";
265 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
266 | "$(inherited)"
267 | );
268 | SWIFT_VERSION = "5.0";
269 | TARGET_NAME = "MOLH";
270 | TVOS_DEPLOYMENT_TARGET = "9.0";
271 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
272 | };
273 | name = "Release";
274 | };
275 | "OBJ_3" = {
276 | isa = "XCBuildConfiguration";
277 | buildSettings = {
278 | CLANG_ENABLE_OBJC_ARC = "YES";
279 | COMBINE_HIDPI_IMAGES = "YES";
280 | COPY_PHASE_STRIP = "NO";
281 | DEBUG_INFORMATION_FORMAT = "dwarf";
282 | DYLIB_INSTALL_NAME_BASE = "@rpath";
283 | ENABLE_NS_ASSERTIONS = "YES";
284 | GCC_OPTIMIZATION_LEVEL = "0";
285 | GCC_PREPROCESSOR_DEFINITIONS = (
286 | "$(inherited)",
287 | "SWIFT_PACKAGE=1",
288 | "DEBUG=1"
289 | );
290 | MACOSX_DEPLOYMENT_TARGET = "10.10";
291 | ONLY_ACTIVE_ARCH = "YES";
292 | OTHER_SWIFT_FLAGS = (
293 | "$(inherited)",
294 | "-DXcode"
295 | );
296 | PRODUCT_NAME = "$(TARGET_NAME)";
297 | SDKROOT = "macosx";
298 | SUPPORTED_PLATFORMS = (
299 | "macosx",
300 | "iphoneos",
301 | "iphonesimulator",
302 | "appletvos",
303 | "appletvsimulator",
304 | "watchos",
305 | "watchsimulator"
306 | );
307 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
308 | "$(inherited)",
309 | "SWIFT_PACKAGE",
310 | "DEBUG"
311 | );
312 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
313 | USE_HEADERMAP = "NO";
314 | };
315 | name = "Debug";
316 | };
317 | "OBJ_30" = {
318 | isa = "PBXSourcesBuildPhase";
319 | files = (
320 | "OBJ_31",
321 | "OBJ_32",
322 | "OBJ_33",
323 | "OBJ_34",
324 | "OBJ_35"
325 | );
326 | };
327 | "OBJ_31" = {
328 | isa = "PBXBuildFile";
329 | fileRef = "OBJ_9";
330 | };
331 | "OBJ_32" = {
332 | isa = "PBXBuildFile";
333 | fileRef = "OBJ_10";
334 | };
335 | "OBJ_33" = {
336 | isa = "PBXBuildFile";
337 | fileRef = "OBJ_11";
338 | };
339 | "OBJ_34" = {
340 | isa = "PBXBuildFile";
341 | fileRef = "OBJ_12";
342 | };
343 | "OBJ_35" = {
344 | isa = "PBXBuildFile";
345 | fileRef = "OBJ_13";
346 | };
347 | "OBJ_36" = {
348 | isa = "PBXFrameworksBuildPhase";
349 | files = (
350 | );
351 | };
352 | "OBJ_38" = {
353 | isa = "XCConfigurationList";
354 | buildConfigurations = (
355 | "OBJ_39",
356 | "OBJ_40"
357 | );
358 | defaultConfigurationIsVisible = "0";
359 | defaultConfigurationName = "Release";
360 | };
361 | "OBJ_39" = {
362 | isa = "XCBuildConfiguration";
363 | buildSettings = {
364 | LD = "/usr/bin/true";
365 | OTHER_SWIFT_FLAGS = (
366 | "-swift-version",
367 | "5",
368 | "-I",
369 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2",
370 | "-target",
371 | "x86_64-apple-macosx10.10",
372 | "-sdk",
373 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk",
374 | "-package-description-version",
375 | "5.1"
376 | );
377 | SWIFT_VERSION = "5.0";
378 | };
379 | name = "Debug";
380 | };
381 | "OBJ_4" = {
382 | isa = "XCBuildConfiguration";
383 | buildSettings = {
384 | CLANG_ENABLE_OBJC_ARC = "YES";
385 | COMBINE_HIDPI_IMAGES = "YES";
386 | COPY_PHASE_STRIP = "YES";
387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
388 | DYLIB_INSTALL_NAME_BASE = "@rpath";
389 | GCC_OPTIMIZATION_LEVEL = "s";
390 | GCC_PREPROCESSOR_DEFINITIONS = (
391 | "$(inherited)",
392 | "SWIFT_PACKAGE=1"
393 | );
394 | MACOSX_DEPLOYMENT_TARGET = "10.10";
395 | OTHER_SWIFT_FLAGS = (
396 | "$(inherited)",
397 | "-DXcode"
398 | );
399 | PRODUCT_NAME = "$(TARGET_NAME)";
400 | SDKROOT = "macosx";
401 | SUPPORTED_PLATFORMS = (
402 | "macosx",
403 | "iphoneos",
404 | "iphonesimulator",
405 | "appletvos",
406 | "appletvsimulator",
407 | "watchos",
408 | "watchsimulator"
409 | );
410 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
411 | "$(inherited)",
412 | "SWIFT_PACKAGE"
413 | );
414 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
415 | USE_HEADERMAP = "NO";
416 | };
417 | name = "Release";
418 | };
419 | "OBJ_40" = {
420 | isa = "XCBuildConfiguration";
421 | buildSettings = {
422 | LD = "/usr/bin/true";
423 | OTHER_SWIFT_FLAGS = (
424 | "-swift-version",
425 | "5",
426 | "-I",
427 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2",
428 | "-target",
429 | "x86_64-apple-macosx10.10",
430 | "-sdk",
431 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk",
432 | "-package-description-version",
433 | "5.1"
434 | );
435 | SWIFT_VERSION = "5.0";
436 | };
437 | name = "Release";
438 | };
439 | "OBJ_41" = {
440 | isa = "PBXSourcesBuildPhase";
441 | files = (
442 | "OBJ_42"
443 | );
444 | };
445 | "OBJ_42" = {
446 | isa = "PBXBuildFile";
447 | fileRef = "OBJ_6";
448 | };
449 | "OBJ_44" = {
450 | isa = "XCConfigurationList";
451 | buildConfigurations = (
452 | "OBJ_45",
453 | "OBJ_46"
454 | );
455 | defaultConfigurationIsVisible = "0";
456 | defaultConfigurationName = "Release";
457 | };
458 | "OBJ_45" = {
459 | isa = "XCBuildConfiguration";
460 | buildSettings = {
461 | };
462 | name = "Debug";
463 | };
464 | "OBJ_46" = {
465 | isa = "XCBuildConfiguration";
466 | buildSettings = {
467 | };
468 | name = "Release";
469 | };
470 | "OBJ_47" = {
471 | isa = "PBXTargetDependency";
472 | target = "MOLH::MOLHTests";
473 | };
474 | "OBJ_49" = {
475 | isa = "XCConfigurationList";
476 | buildConfigurations = (
477 | "OBJ_50",
478 | "OBJ_51"
479 | );
480 | defaultConfigurationIsVisible = "0";
481 | defaultConfigurationName = "Release";
482 | };
483 | "OBJ_5" = {
484 | isa = "PBXGroup";
485 | children = (
486 | "OBJ_6",
487 | "OBJ_7",
488 | "OBJ_14",
489 | "OBJ_18",
490 | "OBJ_21",
491 | "OBJ_22",
492 | "OBJ_23",
493 | "OBJ_24",
494 | "OBJ_25"
495 | );
496 | path = "";
497 | sourceTree = "";
498 | };
499 | "OBJ_50" = {
500 | isa = "XCBuildConfiguration";
501 | buildSettings = {
502 | CLANG_ENABLE_MODULES = "YES";
503 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES";
504 | FRAMEWORK_SEARCH_PATHS = (
505 | "$(inherited)",
506 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
507 | );
508 | HEADER_SEARCH_PATHS = (
509 | "$(inherited)"
510 | );
511 | INFOPLIST_FILE = "MOLH.xcodeproj/MOLHTests_Info.plist";
512 | IPHONEOS_DEPLOYMENT_TARGET = "10.0";
513 | LD_RUNPATH_SEARCH_PATHS = (
514 | "$(inherited)",
515 | "@loader_path/../Frameworks",
516 | "@loader_path/Frameworks"
517 | );
518 | MACOSX_DEPLOYMENT_TARGET = "10.10";
519 | OTHER_CFLAGS = (
520 | "$(inherited)"
521 | );
522 | OTHER_LDFLAGS = (
523 | "$(inherited)"
524 | );
525 | OTHER_SWIFT_FLAGS = (
526 | "$(inherited)"
527 | );
528 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
529 | "$(inherited)"
530 | );
531 | SWIFT_VERSION = "5.0";
532 | TARGET_NAME = "MOLHTests";
533 | TVOS_DEPLOYMENT_TARGET = "9.0";
534 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
535 | };
536 | name = "Debug";
537 | };
538 | "OBJ_51" = {
539 | isa = "XCBuildConfiguration";
540 | buildSettings = {
541 | CLANG_ENABLE_MODULES = "YES";
542 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES";
543 | FRAMEWORK_SEARCH_PATHS = (
544 | "$(inherited)",
545 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
546 | );
547 | HEADER_SEARCH_PATHS = (
548 | "$(inherited)"
549 | );
550 | INFOPLIST_FILE = "MOLH.xcodeproj/MOLHTests_Info.plist";
551 | IPHONEOS_DEPLOYMENT_TARGET = "10.0";
552 | LD_RUNPATH_SEARCH_PATHS = (
553 | "$(inherited)",
554 | "@loader_path/../Frameworks",
555 | "@loader_path/Frameworks"
556 | );
557 | MACOSX_DEPLOYMENT_TARGET = "10.10";
558 | OTHER_CFLAGS = (
559 | "$(inherited)"
560 | );
561 | OTHER_LDFLAGS = (
562 | "$(inherited)"
563 | );
564 | OTHER_SWIFT_FLAGS = (
565 | "$(inherited)"
566 | );
567 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
568 | "$(inherited)"
569 | );
570 | SWIFT_VERSION = "5.0";
571 | TARGET_NAME = "MOLHTests";
572 | TVOS_DEPLOYMENT_TARGET = "9.0";
573 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
574 | };
575 | name = "Release";
576 | };
577 | "OBJ_52" = {
578 | isa = "PBXSourcesBuildPhase";
579 | files = (
580 | "OBJ_53",
581 | "OBJ_54"
582 | );
583 | };
584 | "OBJ_53" = {
585 | isa = "PBXBuildFile";
586 | fileRef = "OBJ_16";
587 | };
588 | "OBJ_54" = {
589 | isa = "PBXBuildFile";
590 | fileRef = "OBJ_17";
591 | };
592 | "OBJ_55" = {
593 | isa = "PBXFrameworksBuildPhase";
594 | files = (
595 | "OBJ_56"
596 | );
597 | };
598 | "OBJ_56" = {
599 | isa = "PBXBuildFile";
600 | fileRef = "MOLH::MOLH::Product";
601 | };
602 | "OBJ_57" = {
603 | isa = "PBXTargetDependency";
604 | target = "MOLH::MOLH";
605 | };
606 | "OBJ_6" = {
607 | isa = "PBXFileReference";
608 | explicitFileType = "sourcecode.swift";
609 | path = "Package.swift";
610 | sourceTree = "";
611 | };
612 | "OBJ_7" = {
613 | isa = "PBXGroup";
614 | children = (
615 | "OBJ_8"
616 | );
617 | name = "Sources";
618 | path = "";
619 | sourceTree = "SOURCE_ROOT";
620 | };
621 | "OBJ_8" = {
622 | isa = "PBXGroup";
623 | children = (
624 | "OBJ_9",
625 | "OBJ_10",
626 | "OBJ_11",
627 | "OBJ_12",
628 | "OBJ_13"
629 | );
630 | name = "MOLH";
631 | path = "Sources/MOLH";
632 | sourceTree = "SOURCE_ROOT";
633 | };
634 | "OBJ_9" = {
635 | isa = "PBXFileReference";
636 | path = "MOLH.swift";
637 | sourceTree = "";
638 | };
639 | };
640 | rootObject = "OBJ_1";
641 | }
642 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | EC07B15428491341009C9FCE /* InformationTextView.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC07B15328491341009C9FCE /* InformationTextView.xib */; };
11 | EC15335321F39E440048AB78 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC15335521F39E440048AB78 /* Main.storyboard */; };
12 | EC1F34662821477F00C0286B /* StackViewTestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1F34652821477F00C0286B /* StackViewTestViewController.swift */; };
13 | EC48F76D238186500095E588 /* MOLHFontLocalizableViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC48F768238186500095E588 /* MOLHFontLocalizableViews.swift */; };
14 | EC48F76E238186500095E588 /* MOLHFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC48F769238186500095E588 /* MOLHFont.swift */; };
15 | EC48F76F238186500095E588 /* MOLH.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC48F76A238186500095E588 /* MOLH.swift */; };
16 | EC48F770238186500095E588 /* MOLHSizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC48F76B238186500095E588 /* MOLHSizable.swift */; };
17 | EC48F771238186500095E588 /* MOLHLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC48F76C238186500095E588 /* MOLHLanguage.swift */; };
18 | EC5B8FEC1EE0ECA4003BE809 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5B8FEB1EE0ECA4003BE809 /* AppDelegate.swift */; };
19 | EC5B8FEE1EE0ECA4003BE809 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5B8FED1EE0ECA4003BE809 /* ViewController.swift */; };
20 | EC5B8FF31EE0ECA4003BE809 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC5B8FF21EE0ECA4003BE809 /* Assets.xcassets */; };
21 | EC5B8FF61EE0ECA4003BE809 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC5B8FF41EE0ECA4003BE809 /* LaunchScreen.storyboard */; };
22 | ECE2F0C321FB72AD009D506D /* MOLH.podspec in Resources */ = {isa = PBXBuildFile; fileRef = ECE2F0C221FB72AC009D506D /* MOLH.podspec */; };
23 | ECE534921EE2237300EBB394 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ECE534941EE2237300EBB394 /* Localizable.strings */; };
24 | ECE534981EE226F300EBB394 /* arrow-right.png in Resources */ = {isa = PBXBuildFile; fileRef = ECE534971EE226F300EBB394 /* arrow-right.png */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXFileReference section */
28 | EC07B15328491341009C9FCE /* InformationTextView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InformationTextView.xib; sourceTree = ""; };
29 | EC15335821F39E790048AB78 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
30 | EC15335A21F39E7C0048AB78 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = ""; };
31 | EC15335B21F39E810048AB78 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Main.strings; sourceTree = ""; };
32 | EC1F34652821477F00C0286B /* StackViewTestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackViewTestViewController.swift; sourceTree = ""; };
33 | EC3E86B9226F1AB200EDE6EE /* agq-CM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "agq-CM"; path = "agq-CM.lproj/Main.strings"; sourceTree = ""; };
34 | EC3E86BA226F1AB200EDE6EE /* agq-CM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "agq-CM"; path = "agq-CM.lproj/LaunchScreen.strings"; sourceTree = ""; };
35 | EC3E86BB226F1AB200EDE6EE /* agq-CM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "agq-CM"; path = "agq-CM.lproj/Localizable.strings"; sourceTree = ""; };
36 | EC48F768238186500095E588 /* MOLHFontLocalizableViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MOLHFontLocalizableViews.swift; path = ../Sources/MOLH/MOLHFontLocalizableViews.swift; sourceTree = ""; };
37 | EC48F769238186500095E588 /* MOLHFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MOLHFont.swift; path = ../Sources/MOLH/MOLHFont.swift; sourceTree = ""; };
38 | EC48F76A238186500095E588 /* MOLH.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MOLH.swift; path = ../Sources/MOLH/MOLH.swift; sourceTree = ""; };
39 | EC48F76B238186500095E588 /* MOLHSizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MOLHSizable.swift; path = ../Sources/MOLH/MOLHSizable.swift; sourceTree = ""; };
40 | EC48F76C238186500095E588 /* MOLHLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MOLHLanguage.swift; path = ../Sources/MOLH/MOLHLanguage.swift; sourceTree = ""; };
41 | EC5B8FE81EE0ECA4003BE809 /* LocalizationHelperDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LocalizationHelperDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
42 | EC5B8FEB1EE0ECA4003BE809 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
43 | EC5B8FED1EE0ECA4003BE809 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
44 | EC5B8FF21EE0ECA4003BE809 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
45 | EC5B8FF51EE0ECA4003BE809 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
46 | EC5B8FF71EE0ECA4003BE809 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | ECB7A11D22C6740500E90F40 /* he-IL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "he-IL"; path = "he-IL.lproj/Main.strings"; sourceTree = ""; };
48 | ECB7A11E22C6740500E90F40 /* he-IL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "he-IL"; path = "he-IL.lproj/LaunchScreen.strings"; sourceTree = ""; };
49 | ECB7A11F22C6740500E90F40 /* he-IL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "he-IL"; path = "he-IL.lproj/Localizable.strings"; sourceTree = ""; };
50 | ECB7A12022C6742300E90F40 /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/Main.strings; sourceTree = ""; };
51 | ECB7A12122C6742300E90F40 /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/LaunchScreen.strings; sourceTree = ""; };
52 | ECB7A12222C6742300E90F40 /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/Localizable.strings; sourceTree = ""; };
53 | ECB7A12322C6746B00E90F40 /* ckb-IQ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IQ"; path = "ckb-IQ.lproj/Main.strings"; sourceTree = ""; };
54 | ECB7A12422C6746B00E90F40 /* ckb-IQ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IQ"; path = "ckb-IQ.lproj/LaunchScreen.strings"; sourceTree = ""; };
55 | ECB7A12522C6746B00E90F40 /* ckb-IQ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IQ"; path = "ckb-IQ.lproj/Localizable.strings"; sourceTree = ""; };
56 | ECB7A12622C6747700E90F40 /* ckb-IR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IR"; path = "ckb-IR.lproj/Main.strings"; sourceTree = ""; };
57 | ECB7A12722C6747700E90F40 /* ckb-IR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IR"; path = "ckb-IR.lproj/LaunchScreen.strings"; sourceTree = ""; };
58 | ECB7A12822C6747700E90F40 /* ckb-IR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ckb-IR"; path = "ckb-IR.lproj/Localizable.strings"; sourceTree = ""; };
59 | ECE2F0C221FB72AC009D506D /* MOLH.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = MOLH.podspec; path = ../../MOLH.podspec; sourceTree = ""; };
60 | ECE534911EE2236800EBB394 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LaunchScreen.strings; sourceTree = ""; };
61 | ECE534931EE2237300EBB394 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; };
62 | ECE534951EE2237500EBB394 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
63 | ECE534961EE2237600EBB394 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; };
64 | ECE534971EE226F300EBB394 /* arrow-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "arrow-right.png"; sourceTree = ""; };
65 | /* End PBXFileReference section */
66 |
67 | /* Begin PBXFrameworksBuildPhase section */
68 | EC5B8FE51EE0ECA4003BE809 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXFrameworksBuildPhase section */
76 |
77 | /* Begin PBXGroup section */
78 | EC5B8FDF1EE0ECA4003BE809 = {
79 | isa = PBXGroup;
80 | children = (
81 | EC5B8FEA1EE0ECA4003BE809 /* LocalizationHelperDemo */,
82 | EC5B8FE91EE0ECA4003BE809 /* Products */,
83 | );
84 | sourceTree = "";
85 | };
86 | EC5B8FE91EE0ECA4003BE809 /* Products */ = {
87 | isa = PBXGroup;
88 | children = (
89 | EC5B8FE81EE0ECA4003BE809 /* LocalizationHelperDemo.app */,
90 | );
91 | name = Products;
92 | sourceTree = "";
93 | };
94 | EC5B8FEA1EE0ECA4003BE809 /* LocalizationHelperDemo */ = {
95 | isa = PBXGroup;
96 | children = (
97 | EC9594B71F29EC63006984E0 /* MOLH */,
98 | EC5B8FEB1EE0ECA4003BE809 /* AppDelegate.swift */,
99 | EC5B8FED1EE0ECA4003BE809 /* ViewController.swift */,
100 | EC07B15328491341009C9FCE /* InformationTextView.xib */,
101 | EC1F34652821477F00C0286B /* StackViewTestViewController.swift */,
102 | ECE2F0C221FB72AC009D506D /* MOLH.podspec */,
103 | ECE534941EE2237300EBB394 /* Localizable.strings */,
104 | EC15335521F39E440048AB78 /* Main.storyboard */,
105 | EC5B8FF21EE0ECA4003BE809 /* Assets.xcassets */,
106 | EC5B8FF41EE0ECA4003BE809 /* LaunchScreen.storyboard */,
107 | ECE534971EE226F300EBB394 /* arrow-right.png */,
108 | EC5B8FF71EE0ECA4003BE809 /* Info.plist */,
109 | );
110 | path = LocalizationHelperDemo;
111 | sourceTree = "";
112 | };
113 | EC9594B71F29EC63006984E0 /* MOLH */ = {
114 | isa = PBXGroup;
115 | children = (
116 | EC48F76A238186500095E588 /* MOLH.swift */,
117 | EC48F769238186500095E588 /* MOLHFont.swift */,
118 | EC48F768238186500095E588 /* MOLHFontLocalizableViews.swift */,
119 | EC48F76C238186500095E588 /* MOLHLanguage.swift */,
120 | EC48F76B238186500095E588 /* MOLHSizable.swift */,
121 | );
122 | name = MOLH;
123 | path = ../../MOLH;
124 | sourceTree = "";
125 | };
126 | /* End PBXGroup section */
127 |
128 | /* Begin PBXNativeTarget section */
129 | EC5B8FE71EE0ECA4003BE809 /* LocalizationHelperDemo */ = {
130 | isa = PBXNativeTarget;
131 | buildConfigurationList = EC5B8FFA1EE0ECA4003BE809 /* Build configuration list for PBXNativeTarget "LocalizationHelperDemo" */;
132 | buildPhases = (
133 | EC5B8FE41EE0ECA4003BE809 /* Sources */,
134 | EC5B8FE51EE0ECA4003BE809 /* Frameworks */,
135 | EC5B8FE61EE0ECA4003BE809 /* Resources */,
136 | );
137 | buildRules = (
138 | );
139 | dependencies = (
140 | );
141 | name = LocalizationHelperDemo;
142 | productName = LocalizationHelperDemo;
143 | productReference = EC5B8FE81EE0ECA4003BE809 /* LocalizationHelperDemo.app */;
144 | productType = "com.apple.product-type.application";
145 | };
146 | /* End PBXNativeTarget section */
147 |
148 | /* Begin PBXProject section */
149 | EC5B8FE01EE0ECA4003BE809 /* Project object */ = {
150 | isa = PBXProject;
151 | attributes = {
152 | LastSwiftUpdateCheck = 0830;
153 | LastUpgradeCheck = 0930;
154 | ORGANIZATIONNAME = Moath;
155 | TargetAttributes = {
156 | EC5B8FE71EE0ECA4003BE809 = {
157 | CreatedOnToolsVersion = 8.3.2;
158 | DevelopmentTeam = 5YP97VN386;
159 | LastSwiftMigration = 1000;
160 | ProvisioningStyle = Automatic;
161 | };
162 | };
163 | };
164 | buildConfigurationList = EC5B8FE31EE0ECA4003BE809 /* Build configuration list for PBXProject "LocalizationHelperDemo" */;
165 | compatibilityVersion = "Xcode 3.2";
166 | developmentRegion = English;
167 | hasScannedForEncodings = 0;
168 | knownRegions = (
169 | English,
170 | en,
171 | Base,
172 | ar,
173 | "agq-CM",
174 | "he-IL",
175 | ur,
176 | "ckb-IQ",
177 | "ckb-IR",
178 | );
179 | mainGroup = EC5B8FDF1EE0ECA4003BE809;
180 | productRefGroup = EC5B8FE91EE0ECA4003BE809 /* Products */;
181 | projectDirPath = "";
182 | projectRoot = "";
183 | targets = (
184 | EC5B8FE71EE0ECA4003BE809 /* LocalizationHelperDemo */,
185 | );
186 | };
187 | /* End PBXProject section */
188 |
189 | /* Begin PBXResourcesBuildPhase section */
190 | EC5B8FE61EE0ECA4003BE809 /* Resources */ = {
191 | isa = PBXResourcesBuildPhase;
192 | buildActionMask = 2147483647;
193 | files = (
194 | ECE2F0C321FB72AD009D506D /* MOLH.podspec in Resources */,
195 | EC15335321F39E440048AB78 /* Main.storyboard in Resources */,
196 | ECE534921EE2237300EBB394 /* Localizable.strings in Resources */,
197 | EC5B8FF61EE0ECA4003BE809 /* LaunchScreen.storyboard in Resources */,
198 | ECE534981EE226F300EBB394 /* arrow-right.png in Resources */,
199 | EC5B8FF31EE0ECA4003BE809 /* Assets.xcassets in Resources */,
200 | EC07B15428491341009C9FCE /* InformationTextView.xib in Resources */,
201 | );
202 | runOnlyForDeploymentPostprocessing = 0;
203 | };
204 | /* End PBXResourcesBuildPhase section */
205 |
206 | /* Begin PBXSourcesBuildPhase section */
207 | EC5B8FE41EE0ECA4003BE809 /* Sources */ = {
208 | isa = PBXSourcesBuildPhase;
209 | buildActionMask = 2147483647;
210 | files = (
211 | EC48F770238186500095E588 /* MOLHSizable.swift in Sources */,
212 | EC48F76E238186500095E588 /* MOLHFont.swift in Sources */,
213 | EC48F76F238186500095E588 /* MOLH.swift in Sources */,
214 | EC5B8FEE1EE0ECA4003BE809 /* ViewController.swift in Sources */,
215 | EC1F34662821477F00C0286B /* StackViewTestViewController.swift in Sources */,
216 | EC48F76D238186500095E588 /* MOLHFontLocalizableViews.swift in Sources */,
217 | EC48F771238186500095E588 /* MOLHLanguage.swift in Sources */,
218 | EC5B8FEC1EE0ECA4003BE809 /* AppDelegate.swift in Sources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | /* End PBXSourcesBuildPhase section */
223 |
224 | /* Begin PBXVariantGroup section */
225 | EC15335521F39E440048AB78 /* Main.storyboard */ = {
226 | isa = PBXVariantGroup;
227 | children = (
228 | EC15335821F39E790048AB78 /* Base */,
229 | EC15335A21F39E7C0048AB78 /* en */,
230 | EC15335B21F39E810048AB78 /* ar */,
231 | EC3E86B9226F1AB200EDE6EE /* agq-CM */,
232 | ECB7A11D22C6740500E90F40 /* he-IL */,
233 | ECB7A12022C6742300E90F40 /* ur */,
234 | ECB7A12322C6746B00E90F40 /* ckb-IQ */,
235 | ECB7A12622C6747700E90F40 /* ckb-IR */,
236 | );
237 | name = Main.storyboard;
238 | sourceTree = "";
239 | };
240 | EC5B8FF41EE0ECA4003BE809 /* LaunchScreen.storyboard */ = {
241 | isa = PBXVariantGroup;
242 | children = (
243 | EC5B8FF51EE0ECA4003BE809 /* Base */,
244 | ECE534911EE2236800EBB394 /* ar */,
245 | EC3E86BA226F1AB200EDE6EE /* agq-CM */,
246 | ECB7A11E22C6740500E90F40 /* he-IL */,
247 | ECB7A12122C6742300E90F40 /* ur */,
248 | ECB7A12422C6746B00E90F40 /* ckb-IQ */,
249 | ECB7A12722C6747700E90F40 /* ckb-IR */,
250 | );
251 | name = LaunchScreen.storyboard;
252 | sourceTree = "";
253 | };
254 | ECE534941EE2237300EBB394 /* Localizable.strings */ = {
255 | isa = PBXVariantGroup;
256 | children = (
257 | ECE534931EE2237300EBB394 /* Base */,
258 | ECE534951EE2237500EBB394 /* en */,
259 | ECE534961EE2237600EBB394 /* ar */,
260 | EC3E86BB226F1AB200EDE6EE /* agq-CM */,
261 | ECB7A11F22C6740500E90F40 /* he-IL */,
262 | ECB7A12222C6742300E90F40 /* ur */,
263 | ECB7A12522C6746B00E90F40 /* ckb-IQ */,
264 | ECB7A12822C6747700E90F40 /* ckb-IR */,
265 | );
266 | name = Localizable.strings;
267 | sourceTree = "";
268 | };
269 | /* End PBXVariantGroup section */
270 |
271 | /* Begin XCBuildConfiguration section */
272 | EC5B8FF81EE0ECA4003BE809 /* Debug */ = {
273 | isa = XCBuildConfiguration;
274 | buildSettings = {
275 | ALWAYS_SEARCH_USER_PATHS = NO;
276 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
277 | CLANG_ANALYZER_NONNULL = YES;
278 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
280 | CLANG_CXX_LIBRARY = "libc++";
281 | CLANG_ENABLE_MODULES = YES;
282 | CLANG_ENABLE_OBJC_ARC = YES;
283 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
284 | CLANG_WARN_BOOL_CONVERSION = YES;
285 | CLANG_WARN_COMMA = YES;
286 | CLANG_WARN_CONSTANT_CONVERSION = YES;
287 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
288 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
289 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
290 | CLANG_WARN_EMPTY_BODY = YES;
291 | CLANG_WARN_ENUM_CONVERSION = YES;
292 | CLANG_WARN_INFINITE_RECURSION = YES;
293 | CLANG_WARN_INT_CONVERSION = YES;
294 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
295 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
296 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
297 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
298 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
299 | CLANG_WARN_STRICT_PROTOTYPES = YES;
300 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
301 | CLANG_WARN_UNREACHABLE_CODE = YES;
302 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
303 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
304 | COPY_PHASE_STRIP = NO;
305 | DEBUG_INFORMATION_FORMAT = dwarf;
306 | ENABLE_STRICT_OBJC_MSGSEND = YES;
307 | ENABLE_TESTABILITY = YES;
308 | GCC_C_LANGUAGE_STANDARD = gnu99;
309 | GCC_DYNAMIC_NO_PIC = NO;
310 | GCC_NO_COMMON_BLOCKS = YES;
311 | GCC_OPTIMIZATION_LEVEL = 0;
312 | GCC_PREPROCESSOR_DEFINITIONS = (
313 | "DEBUG=1",
314 | "$(inherited)",
315 | );
316 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
317 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
318 | GCC_WARN_UNDECLARED_SELECTOR = YES;
319 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
320 | GCC_WARN_UNUSED_FUNCTION = YES;
321 | GCC_WARN_UNUSED_VARIABLE = YES;
322 | IPHONEOS_DEPLOYMENT_TARGET = 9;
323 | MTL_ENABLE_DEBUG_INFO = YES;
324 | ONLY_ACTIVE_ARCH = YES;
325 | SDKROOT = iphoneos;
326 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
327 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
328 | };
329 | name = Debug;
330 | };
331 | EC5B8FF91EE0ECA4003BE809 /* Release */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_SEARCH_USER_PATHS = NO;
335 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
336 | CLANG_ANALYZER_NONNULL = YES;
337 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
338 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
339 | CLANG_CXX_LIBRARY = "libc++";
340 | CLANG_ENABLE_MODULES = YES;
341 | CLANG_ENABLE_OBJC_ARC = YES;
342 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
343 | CLANG_WARN_BOOL_CONVERSION = YES;
344 | CLANG_WARN_COMMA = YES;
345 | CLANG_WARN_CONSTANT_CONVERSION = YES;
346 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
348 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
349 | CLANG_WARN_EMPTY_BODY = YES;
350 | CLANG_WARN_ENUM_CONVERSION = YES;
351 | CLANG_WARN_INFINITE_RECURSION = YES;
352 | CLANG_WARN_INT_CONVERSION = YES;
353 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
354 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
355 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
357 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
358 | CLANG_WARN_STRICT_PROTOTYPES = YES;
359 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
360 | CLANG_WARN_UNREACHABLE_CODE = YES;
361 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
362 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
363 | COPY_PHASE_STRIP = NO;
364 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
365 | ENABLE_NS_ASSERTIONS = NO;
366 | ENABLE_STRICT_OBJC_MSGSEND = YES;
367 | GCC_C_LANGUAGE_STANDARD = gnu99;
368 | GCC_NO_COMMON_BLOCKS = YES;
369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
371 | GCC_WARN_UNDECLARED_SELECTOR = YES;
372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
373 | GCC_WARN_UNUSED_FUNCTION = YES;
374 | GCC_WARN_UNUSED_VARIABLE = YES;
375 | IPHONEOS_DEPLOYMENT_TARGET = 9;
376 | MTL_ENABLE_DEBUG_INFO = NO;
377 | SDKROOT = iphoneos;
378 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
379 | VALIDATE_PRODUCT = YES;
380 | };
381 | name = Release;
382 | };
383 | EC5B8FFB1EE0ECA4003BE809 /* Debug */ = {
384 | isa = XCBuildConfiguration;
385 | buildSettings = {
386 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
387 | DEVELOPMENT_TEAM = 5YP97VN386;
388 | INFOPLIST_FILE = LocalizationHelperDemo/Info.plist;
389 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
390 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
391 | PRODUCT_BUNDLE_IDENTIFIER = com.whitetorch.LocalizationHelperDemo;
392 | PRODUCT_NAME = "$(TARGET_NAME)";
393 | SWIFT_VERSION = 5.0;
394 | };
395 | name = Debug;
396 | };
397 | EC5B8FFC1EE0ECA4003BE809 /* Release */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
401 | DEVELOPMENT_TEAM = 5YP97VN386;
402 | INFOPLIST_FILE = LocalizationHelperDemo/Info.plist;
403 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
404 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
405 | PRODUCT_BUNDLE_IDENTIFIER = com.whitetorch.LocalizationHelperDemo;
406 | PRODUCT_NAME = "$(TARGET_NAME)";
407 | SWIFT_VERSION = 5.0;
408 | };
409 | name = Release;
410 | };
411 | /* End XCBuildConfiguration section */
412 |
413 | /* Begin XCConfigurationList section */
414 | EC5B8FE31EE0ECA4003BE809 /* Build configuration list for PBXProject "LocalizationHelperDemo" */ = {
415 | isa = XCConfigurationList;
416 | buildConfigurations = (
417 | EC5B8FF81EE0ECA4003BE809 /* Debug */,
418 | EC5B8FF91EE0ECA4003BE809 /* Release */,
419 | );
420 | defaultConfigurationIsVisible = 0;
421 | defaultConfigurationName = Release;
422 | };
423 | EC5B8FFA1EE0ECA4003BE809 /* Build configuration list for PBXNativeTarget "LocalizationHelperDemo" */ = {
424 | isa = XCConfigurationList;
425 | buildConfigurations = (
426 | EC5B8FFB1EE0ECA4003BE809 /* Debug */,
427 | EC5B8FFC1EE0ECA4003BE809 /* Release */,
428 | );
429 | defaultConfigurationIsVisible = 0;
430 | defaultConfigurationName = Release;
431 | };
432 | /* End XCConfigurationList section */
433 | };
434 | rootObject = EC5B8FE01EE0ECA4003BE809 /* Project object */;
435 | }
436 |
--------------------------------------------------------------------------------
/LocalizationHelperDemo/LocalizationHelperDemo/Base.lproj/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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
71 |
77 |
78 |
79 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
215 |
216 |
217 |
218 |
219 |
220 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
--------------------------------------------------------------------------------