Laurine - Localization code generator written in Swift. Sweet!

Related tags

Tools Laurine
Overview

Author's note: Thanks everyone for making Laurine the TOP trending Swift repository in the world - this is amazing and very heart-warming! But this is just the beginning.

For the last few years, my team and I worked on a tool to completely change mobile programming - make it way faster and more fun for everyone - and we are nearly ready to release it to the world. If you are interested, head over to Product Hunt and check it out!

Swift 3.2 Swift 4.0 Platforms OS X | iOS | tvos License Contact Me

Laurine

Localization code generator written (with love) for Swift, intended to end the constant problems that localizations present developers.

Too tired to read? That is understandable. That is why I made this example. You will find it little bit different from what you usually see - check it out. Just download and run in Xcode.

Latest version of laurine now supports Swift 3.2 / 4.0 and higher (XCode 9). Looking for version compatible with XCode 8? We have that as well - switch to S3 branch. Looking for version compatible with Swift 2? Here you go - switch to S2 branch.

Do I need it? (Yes, you do)

Laurine is a clever Swift script that scans your localization file and generates structured, high-performance code out of it (in both ObjC or Swift, your call), thereby making the usage of localization strings much easier and safer.

The great thing is that by removing magical strings from your code, the compiler can actually tell you when you forget to make changes (and where), if your localization file changes. It also introduces type checking for strings that contain runtime format specifiers (%@, %d etc.).

Laurine requires Swift to run and can be used from the command line as well as from a build script (recommended). Laurine uses CommandLine to parse command line arguemnts: no extra configuration is needed.

What do I get?

Once you run Laurine, the output will be one .swift or .m file containing a Localizations structure / object. From this single access point, you will get access to all the sweetness:

Variables

For each string that does not contain any special characters, a property is generated. For example:

"PROFILE_PHONE_NUMBER" = "Your phone number!"

can be then used like this:

self.labelToLocalize.text = Localizations.ProfilePhoneNumber

in Xcode, autocomplete is actually, for once, really helpful! Madness.

Image : Xcode help for variables

Methods

If your localization string has runtime format specifiers, it is generated as a method instead. Laurine detects the format specifiers and generates a proper method header from that definition. There is no limit to how many of them you have.

For example:

"PROFILE_INFO" = "I am %@, I am %d years old and %.2fm in height!"

can be then used like this:

self.labelToLocalize.text = Localizations.ProfileInfo("Jiri", 25, 1.75)

Once again, Xcode autocomplete for the win! Insanity.

Image : XCode help for methods

Swift support

Swift-written application is recommended Laurine usecase. Internally, it uses nested structures to make your life much easier. Also, it is extremely performant and will have no impact on your current codebase.

ObjC support

Objective-C is supported from v0.2 as well. Because of the way the code is generated, you can write just the same code as you would in Swift, using dot notation to access each next element. For example:

NSString *text = Localizations.ProfileInfo("Jiri", 25, 1.75)

This produces exactly the same result as you would get in Swift and is recommended.

Nested Structures

It is best practice to make the keys as descriptive and structured as possible. Laurine takes advantage of that to generate nested structures rather than overly long key names. For example:

"PROFILE-NAVIGATION_BAR-ITEMS-DONE" = "Done" // -c -d -
"PROFILE.NAVIGATION_BAR.ITEMS.DONE" = "Done" // -c -d .

Is actually converted to:

self.labelToLocalize.text = Localizations.Profile.NavigationBar.Items.Done

This way, you can easily traverse through thousands of strings without even thinking about it (obviously, how you actually group your strings is up to you).

You can use -d "delimiter" option to specify which character you would like to use for nesting, defaults to - (slash).

Use _ (underscore) to make camel case strings (MY_AWESOME_WORD to MyAwesomeKey), or omit "c" option to disable this feature.

Note: Language-specific keywords (such as Swift: func and ObjC: YES) and names starting with numbers (Profile.1stButton) will get prefixed with _ to prevent build errors.

Usage

Laurine uses script parameters to change the way how output is generated. Currently, the following is supported:

  -i, --input:     
      Required | String | Path to the localization file
  -o, --output:    
      Optional | String | Path to output file (.swift or .m, depending on your configuration. If you are using ObjC, header will be created on that location. If ommited, output will be sent to stdout instead.
  -l, --language:  
      Optional | String | [swift | objc] | Specifies language of generated output files | Defaults to [swift]
  -d, --delimiter: 
      Optional | String | String delimiter to separate segments of each string | Defaults to [.]
  -c, --capitalize:
      Optional | Bool | When enabled, name of all structures / methods / properties are automatically CamelCased | Defaults to false

Command line

If you wish to generate output just once, run following from terminal in the directory where you have the script downloaded:

$ swift LaurineGenerator.swift -i Localizable.strings -c -o Localizations.swift
or for ObjC
$ swift LaurineGenerator.swift -i Localizable.strings -c -o Localizations.m -l objc

or, alternatively, if you downloaded it through Brew:

$ LaurineGenerator.swift -i Localizable.strings -c -o Localizations.swift
or for ObjC
$ LaurineGenerator.swift -i Localizable.strings -c -o Localizations.m -l objc

Build script

The recommended way to use Laurine is to create a "Run Script" Build Phase (Xcode > Project > Targets > Your build target > Build Phases > New Run Script Phase). This way, Laurine will be executed before each build and will ensure the integrity of your translations. Be sure to put the script before the "Compile Sources" phase, as it has to generate the code first, before it can be used anywhere else. For convenience, you can just copy the following, and change the configuration appropriately.

 set -x
 
 # Get base path to project
 BASE_PATH="$PROJECT_DIR/$PROJECT_NAME"
 
 #--------- START OF YOUR CONFIGURATION (change Path_To_.. to fit)
 
 # Get path to Laurine Generator script
 LAURINE_PATH="$BASE_PATH/Path_To_Generator/LaurineGenerator.swift"
 
 # Get path to main localization file (usually english).
 SOURCE_PATH="$BASE_PATH/Path_To_Base_Localization/Localizable.strings"
 
 # Get path to output. If you use ObjC version of output, set implementation file (.m), as header will be generated automatically
 OUTPUT_PATH="$BASE_PATH/Path_To_Output/Localizations.swift"
 
 #--------- END OF YOUR CONFIGURATION
 
 # Add permission to generator for script execution
 chmod 755 "$LAURINE_PATH"
 
 # Actually generate output. -- CUSTOMIZE -- parameters to your needs (see documentation). 
 # Will only re-generate script if something changed
 if [ "$OUTPUT_PATH" -ot "$SOURCE_PATH" ]; then
    "$LAURINE_PATH" -i "$SOURCE_PATH" -o "$OUTPUT_PATH"
 fi

Installation

Brew

Laurine does not require installation. For your convenience, you can make it easily accessible from /usr/local/bin by installing Laurine through brew:

$ brew tap jiritrecak/laurine
$ brew install jiritrecak/laurine/laurine

Now you can just run it from everywhere:

$ LaurineGenerator.swift ...

GIT

You can also just clone it wherever you desire:

$ git clone https://github.com/JiriTrecak/Laurine.git
$ sudo cp laurine.swift /usr/local/bin/laurine.swift

Download!

Yes, you can just download the script itself from this repository, it does not need anything else.

Supported Features

Laurine should suit most of developers, because it covers all the basic stuff. That being said, there are still things missing to have full coverage of what localizations have to offer. Here is the full list of features that will Laurine contain once it is complete:

  • Basic localization strings to variables
  • Complex localization strings to methods
  • Multilevel structures (nesting)
  • Generate Swift output
  • Generate ObjC output
  • Support for all special localization characters
  • Localization Tables
  • Plural support
  • Gender support
  • Tool for automatic replacement of NSLocalizationString in project (thanks @Vaberer )

Contribute

I will gladly accept Pull Requests (and I encourage you to do so). If you encounter any bug or you have enhancement that you would like to see, please open an issue. Please make sure you target your PR against Development branch.

I'd also like to make round of applause to Marcin Krzyżanowski for his Natalie Generator, which heavily inspired this project by his approach. Hope we meet for beer one day!

More libraries, same awesomeness

If you liked it, check out my other library - Warp, that will help you with development of your data models.

Contact me

Or, if you would like to know me better, check out my portfolio.

##Licence

The MIT License (MIT)

Copyright (c) 2015 Jiří Třečák

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Comments
  • Xcode 7.3 support

    Xcode 7.3 support

    First of all: Thanks for developing and sharing Laurine, I really like it a lot!

    Unfortunately with the recent release of Xcode 7.3 Laurine Generator produces the following error and warnings:

    bildschirmfoto 2016-03-24 um 10 48 02

    opened by pixeldock 5
  • error: unknown attribute 'exported'

    error: unknown attribute 'exported'

    Version 7.3 beta (7D129n)

    /usr/local/bin/LaurineGenerator.swift:47:2: error: unknown attribute 'exported'
    @exported import Darwin
    
    ~: brew install jiritrecak/laurine/laurine
    Warning: jiritrecak/laurine/laurine-0.2.0 already installed
    
    opened by Ewg777 5
  • Improvement Request

    Improvement Request

    Hi,

    Regarding Git the script becomes a little annoying because of the timestamp added to the documentation header:

    // // Autogenerated by Laurine - by Jiri Trecak ( http://jiritrecak.com, @jiritrecak ) // Do not change this file manually! // // 2015-12-14 at 5:48 PM //

    That makes the file to be included on every commit just because of the date time update.

    I think there are two options to deal with this:

    1. Do not add it so if there are no updates to the file It will not record anything to git
    2. The best one could be check the OUTPUT_PATH Localization.swift file modification date and compare it to SOURCE_PATH Localizable.strings e.g:

    if Localizable.strings.modificationDate > Localization.swift.modificationDate { do rebuild } else { ignore since there is no changes }

    What do you think?

    enhancement 
    opened by ed-mejia 5
  • Nested Structures don't seem to be working.

    Nested Structures don't seem to be working.

    Nested Structures don't seem to be working in the latest version on github for Swift. I tried both of these: "PROFILE-NAVIGATION_BAR-ITEMS-DONE" = "Done" // -c -d - "PROFILE.NAVIGATION_BAR.ITEMS.DONE" = "Done" // -c -d .

    I tried specifying and leaving the defaults, neither worked. I even tried adding a new string to the example and that didn't work.

    It changed it to /// Base translation: Thanks everyone! You rock! public static var ContributorsFooter : String = "Contributors.Footer".localized

    opened by jarleif 4
  • Plural support

    Plural support

    Introduction & My approach

    Hello guys, I am glad you are enjoying this project so much - it is trending, people write about it, and I really strive to make it the ultimate solution for translations in the application.

    Now, the base is already great, but what is really missing is support for Plurals. You probably know how it is done in the iOS - instead of writing it to .strings, you generate .stringsdict (plist, really) that contains rules for how the word should change with different number of X.

    I am not the biggest fan of that approach, but it is what it is and we have to work with what we have (plus there is probably not better solution, I know). I would like to know feedback about this topic. My idea is following:

    • The parser will scan the folder where Localizations.strings reside and look for .stringdict.
    • If it finds it, it will parse it and get all the keys from it
    • For each key / value pair it will generate method the same way as you would use it from standard .strings file

    The output would then look like this:

    Localizations.Profile.Friends(1) // 1 Friend
    Localizations.Profile.Friends(2) // 2 Friends
    Localizations.Profile.Friends(10) // 10 Friends
    

    What do you say? What are your opinions about this?

    Possible enhancement for future version

    Now as I mentioned, I am really not the biggest fan of .stringdict file - it is complicated to write. So I was thinking that it could be possible to write plural localizations directly from strings. Obviously, I would never want to build that decision engine, that is way out of scope of this project and would be completely pointless, but, imagine following. Instead of writing everything to .stringdict, write it to .strings as following:

    "Localizations.Profile.Friends[one]" = "%d Friend";
    "Localizations.Profile.Friends[few]" = "%d Friends";
    "Localizations.Profile.Friends[many]" = "%d Friends";
    

    key in [] is the same key that you would use in dictionary to write rule. Except you would not need the dictionary, because that would be built dynamically by the system and then fed to iOS localization engine (if that is possible, which I am, so far, unsure of.

    Do you think we could change the base format of the localizations and do you think it is viable, or it seems like too much over-engineering and we should just stick with .stringdict?

    Thank you for your feedback!

    help wanted question 
    opened by JiriTrecak 4
  • Deprecated homebrew dependencies

    Deprecated homebrew dependencies

    Warning: Calling Formula.sha1 is deprecated!
    Use Formula.sha256 instead.
    /usr/local/Library/Taps/jiritrecak/homebrew-laurine/laurine.rb:4:in `<class:Laurine>'
    Please report this to the jiritrecak/laurine tap!
    
    Warning: Calling SoftwareSpec#sha1 is deprecated!
    Use SoftwareSpec#sha256 instead.
    /usr/local/Library/Taps/jiritrecak/homebrew-laurine/laurine.rb:4:in `<class:Laurine>'
    Please report this to the jiritrecak/laurine tap!
    
    Warning: Calling Resource#sha1 is deprecated!
    Use Resource#sha256 instead.
    /usr/local/Library/Taps/jiritrecak/homebrew-laurine/laurine.rb:4:in `<class:Laurine>'
    Please report this to the jiritrecak/laurine tap!
    
    opened by esetnik 3
  • Use only alphanumeric values and added safety checks

    Use only alphanumeric values and added safety checks

    Sorry for the last pull request, I messed it up and created a new one :D But good thing: I created it to the develop branch ;) Added method to only use alphanumeric properties (filters out every value and replaces spaces with _) if non conventional localization keys were used :) Added also some safety checks that should add more crash prevention.

    opened by BenchR267 3
  • Fix support for Frameworks

    Fix support for Frameworks

    Hi,

    Actually the code does not support frameworks properly, the generated String extension:

    private extension String {
    
        var localized: String {
            return NSLocalizedString(self, tableName: nil, bundle: NSBundle.mainBundle(), value: "", comment: "")
        }
        func localizedWithComment(comment:String) -> String {
            return NSLocalizedString(self, tableName: nil, bundle: NSBundle.mainBundle(), value: "", comment: comment)
        }
    }
    

    It's using _NSBundle.mainBundle()_, as a result if you call a localized var from the App target, the system will load the localized string from the localization file of that target and not from the framework.

    I'm testing a little hack:

    private extension String {
    
        var localized: String {
            return NSLocalizedString(self, tableName: nil, bundle: NSBundle(forClass: LocalizationsBundleClass.self), value: "", comment: "")
        }
        func localizedWithComment(comment:String) -> String {
            return NSLocalizedString(self, tableName: nil, bundle: NSBundle(forClass: LocalizationsBundleClass.self), value: "", comment: comment)
        }
    }
    internal class LocalizationsBundleClass {}
    

    I created an internal dummy class in order to fetch the correct bundle via:

    NSBundle(forClass: LocalizationsBundleClass.self)
    

    The name of this dummy class should be based on the values in the script e.g: OUTPUT_PATH="$BASE_PATH/Path_To_Output/_Localizations_.swift"

    Although I'm not sure if this is the more optimal solution.

    bug 
    opened by ed-mejia 3
  • Repeated usage

    Repeated usage

    If I understand the usage correctly, you need to remove instances of NSLocalizedString and its variations from your code, and then replace them with the corresponding generated Localizations.… properties and variables.

    But then, this means that genstrings command won't be able to extract these strings again, as it won't find them. How is then further maintenance of Localizable.strings supposed to happen?

    What happens if a string is no longer used in the code? it will live forever in Localizable.strings and Localizations.swift unless manually removed, is that correct?

    opened by victor 3
  • Compatibility with XCode xliff export

    Compatibility with XCode xliff export

    Is there any way to get this to work with the Xcode "Export for localization" functionality? When I create a custom Localizable.strings file to use for Laurine (which rocks by the way), the content of that file does not get exported to my xliff files.

    opened by donaldpiret 3
  • Allow to be used within frameworks

    Allow to be used within frameworks

    Hi, First of all I must to say this Lib is Just AWESOME!..

    One thing is that in my project I'm using a framework to share functionality between extensions and the App, said that I want to keep every single localization string within the framework so it can be used by all the extensions and the App itself.

    But at the moment it's not working because the generated code are not public.

    enhancement 
    opened by ed-mejia 3
  • Xcode 10.2 error

    Xcode 10.2 error

    I get this error when running in Xcode 10.2 - Swift 4.2

    0. Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret /Users/emil/Virksomheder/Projekter/sense-ios/Sense/Sense/Libraries/LaurineGenerator.swift -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -module-name LaurineGenerator -- -i /Users/emil/Virksomheder/Projekter/sense-ios/Sense/Sense/Assets/en.lproj/Localizable.strings -o /Users/emil/Virksomheder/Projekter/sense-ios/Sense/Sense/Helpers/Localizations.swift -c true 0 swift 0x00000001080cfee3 PrintStackTraceSignalHandler(void*) + 51 1 swift 0x00000001080cf6bc SignalHandler(int) + 348 2 libsystem_platform.dylib 0x00007fff71114b5d _sigtramp + 29 3 libsystem_platform.dylib 000000000000000000 _sigtramp + 2398008512 4 libswiftCore.dylib 0x00007fff70959c09 _swift_updateClassMetadataImpl(swift::TargetClassMetadata<swift::InProcess>*, swift::ClassLayoutFlags, unsigned long, swift::TypeLayout const* const*, unsigned long*, bool) + 265 5 libswiftCore.dylib 0x00007fff70959c4b swift_updateClassMetadata2 + 27 6 libswiftCore.dylib 0x000000010b1d14ce swift_updateClassMetadata2 + 2592569502 7 libswiftCore.dylib 0x00007fff70961b77 swift::MetadataCacheEntryBase<(anonymous namespace)::SingletonMetadataCacheEntry, int>::doInitialization(swift::ConcurrencyControl&, swift::MetadataCompletionQueueEntry*, swift::MetadataRequest) + 215 8 libswiftCore.dylib 0x00007fff709573f3 swift_getSingletonMetadata + 579 9 libswiftCore.dylib 0x000000010b1b01af swift_getSingletonMetadata + 2592444415 10 libswiftCore.dylib 0x000000010b1b013c swift_getSingletonMetadata + 2592444300 11 swift 0x000000010496719d llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 365 12 swift 0x000000010496d572 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1090 13 swift 0x0000000103f365d1 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 58913 14 swift 0x0000000103f246de swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 6862 15 swift 0x0000000103ec27be main + 1246 16 libdyld.dylib 0x00007fff70f2f3d5 start + 1 /Users/emil/Library/Developer/Xcode/DerivedData/Sense-amrxbuahpzprwaepprxlnxrnivph/Build/Intermediates.noindex/Sense.build/Debug-iphoneos/Sense.build/Script-FD357AEE20B807A500F1DB2E.sh: line 27: 6297 Segmentation fault: 11 "$LAURINE_PATH" -i "$SOURCE_PATH" -o "$OUTPUT_PATH" -c true Command PhaseScriptExecution failed with a nonzero exit code

    opened by emilpedersen 20
  • Feature request: use Base translation as comment

    Feature request: use Base translation as comment

    Currently when Laurine generates the static vars, there is no comment:

    public struct Localizations {
        public struct Project {
            public struct Example {
                /// Base translation: An example project
                public static var Title : String = NSLocalizedString("Project.Example.Title", comment: "")
            }
        }
    }
    

    In my case, I use a BartyCrouch script after the Laurine script, which uses the comments to populate all my other translation files (everything is in 24 languages in my app).

    They end up with a useless comment on every key:

    /* No comment provided by engineer. */
    "Project.Regional.Title" = "";
    

    I'd really like to have the option to tell Laurine to use the Base translation as the comment, so to get a better result:

    • Laurine
    public struct Localizations {
        public struct Project {
            public struct Example {
                /// Base translation: An example project
                public static var Title : String = NSLocalizedString("Project.Example.Title", comment: "An example project")
            }
        }
    }
    
    • BartyCrouch
    /* An example project */
    "Project.Regional.Title" = "";
    
    opened by daaa57150 0
  • Feature/podspec

    Feature/podspec

    Hi,

    I added a podspec so that I could use Laurine in my project using cocoapods.

    It's easier for projects already using cocoapods because there is nothing else to install, just add it to the Pod file and do the usual and it's available for the build script. Also the path to use in the build script is the same for everyone.

    I'm using it currently in my project, and I'm happy I can use it this way, because my collaborators won't have any configuration/install to do. Same for the CI, nothing more to configure (although I did not test that yet).

    The PR is there if you want it.

    opened by daaa57150 0
  • Update Swift keywords

    Update Swift keywords

    Add a few missing keywords (fileprivate, open, etc.) that have been introduced in recent Swift versions, and removed some that are no longer available (__FUNCTION__, __FILE__, etc.).

    Used the list of keywords here for reference: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html

    opened by robtimp 0
  • "Error.Title.General" is not recognized by Laurine

    Hi!

    Laurine, for some reason, just doesn't see this localization string: "Error.Title.General". It doesn't even create a top-most struct for the Error. Is it intentional behaviour?

    Thanks in advance.

    opened by soberman 0
Owner
Jiri Trecak
🚀 CEO, Founder of Supernova.io, YC alumni, Forbes 30 under 30
Jiri Trecak
Xcode .appiconset generator for Adobe Illustrator.

Creating AppIcon sets from Adobe Illustrator This repo is rewrited from original repo https://github.com/CaryChamplin/CreatingIconsFromAI. Just genera

gitmerge 73 Nov 9, 2020
AVXCAssets Generator takes path for your assets images and creates appiconset and imageset for you in just one click

AVXCAssets Generator Often while developing an app, We ran into a condition when we need to scale images to each and every aspect ratios for icons and

Angel Vasa 339 Dec 6, 2022
SwiftGen is a tool to automatically generate Swift code for resources of your projects

SwiftGen SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them ty

null 8.3k Jan 5, 2023
An Xcode plug-in to format your code using SwiftLint.

SwiftLintXcode An Xcode plug-in to format your code using SwiftLint. Runs swiftlint autocorrect --path CURRENT_FILE before *.swift file is saved. IMPO

Yuya Tanaka 348 Sep 18, 2022
Swift CLI for strong-typing images, colors, storyboards, fonts and localizations

Shark Shark is a Swift command line tool that generates type safe enums for your images, colors, storyboards, fonts and localizations. Because Shark r

Kaan Dedeoglu 377 Dec 1, 2022
Strong typed, autocompleted resources like images, fonts and segues in Swift projects

R.swift Get strong typed, autocompleted resources like images, fonts and segues in Swift projects Why use this? It makes your code that uses resources

Mathijs Kadijk 8.9k Jan 6, 2023
Soulful docs for Swift & Objective-C

jazzy is a command-line utility that generates documentation for Swift or Objective-C About Both Swift and Objective-C projects are supported. Instead

Realm 7.2k Jan 3, 2023
swiftenv allows you to easily install, and switch between multiple versions of Swift.

Swift Version Manager swiftenv allows you to easily install, and switch between multiple versions of Swift. This project was heavily inspired by pyenv

Kyle Fuller 1.9k Dec 27, 2022
Script to support easily using Xcode Asset Catalog in Swift.

Misen Misen is a script to support using Xcode Asset Catalog in Swift. Features Misen scans sub-directories in the specified Asset Catalog and creates

Kazunobu Tasaka 123 Jun 29, 2022
An Xcode Plugin to convert Objective-C to Swift

XCSwiftr Convert Objective-C code into Swift from within Xcode. This plugin uses the Java applet of objc2swift to do the conversion. Noticed that the

Ignacio Romero Zurbuchen 338 Nov 29, 2022
Swift autocompleter for Sublime Text, via the adorable SourceKitten framework

SwiftKitten SwiftKitten is a Swift autocompleter for Sublime Text, via the adorable SourceKitten framework. Faster than XCode ! This package is new an

John Snyder 142 Sep 9, 2022
Sweet-swift - Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper Functions and Common Utilities

Sweet Swift Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper F

Yanzhan Yang 2 Feb 6, 2022
Will Powell 1.2k Dec 29, 2022
CoreData/Realm sweet wrapper written in Swift

What is SugarRecord? SugarRecord is a persistence wrapper designed to make working with persistence solutions like CoreData in a much easier way. Than

Modo 2.1k Dec 9, 2022
iOS localization swift code generation project

code-gen-library - localization-swift module code-gen-library - localization-swift module with Python bash script execute to localization swift files(

umut boz 0 Oct 26, 2021
✨ Super sweet syntactic sugar for Swift initializers

Then ✨ Super sweet syntactic sugar for Swift initializers. At a Glance Initialize UILabel then set its properties. let label = UILabel().then { $0.t

Suyeol Jeon 4k Jan 4, 2023
A sweet and swifty YAML parser built on LibYAML.

Yams A sweet and swifty YAML parser built on LibYAML. Installation Building Yams requires Xcode 11.x or a Swift 5.1+ toolchain with the Swift Package

JP Simard 930 Jan 4, 2023
✨ Super sweet syntactic sugar for SwiftUI.View initializers.

ViewCondition ✨ Super sweet syntactic sugar for SwiftUI.View initializers. At a Glance struct BorderTextView: View { var color: Color? @ViewBuild

Yoon Joonghyun 76 Dec 17, 2022
Localization/I18n: Incrementally update/translate your Strings files from .swift, .h, .m(m), .storyboard or .xib files.

Installation • Configuration • Usage • Build Script • Donation • Migration Guides • Issues • Contributing • License BartyCrouch BartyCrouch incrementa

Flinesoft 1.3k Jan 1, 2023
Swift friendly localization and i18n with in-app language switching

Localize-Swift Localize-Swift is a simple framework that improves i18n and localization in Swift iOS apps - providing cleaner syntax and in-app langua

Roy Marmelstein 2.9k Dec 29, 2022