Code Monkey home page Code Monkey logo

laurine's People

Contributors

fabb avatar fpillet avatar jiritrecak avatar jlalvarez18 avatar richardbuckle avatar robtimp avatar solidcell avatar victor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laurine's Issues

Support for dictionaries

I need to map error codes to localized strings which currently does not seem to be possible with Laurine (or am I missing something?)

I would like to be able to write something like

let errorMessage = Foo.Bar.ErrorCodes(100500)

or

let errorMessage = Foo.Bar.ErrorCodes[100500]

Question: What about memory?

I read that struct is kept in the memory, so if you have many strings that it might be problematic.
Am I right?

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.

Integration with existing projects

Hello,

Your library seems to be very handy and I really consider it to use it in my projects. What I would appreciate is to somehow help me to substitute all my current NSLocalizedString() in my code into your approach. Because manually changing all my strings is pretty big task and it would definitely be able to do it just with one command/script.

Thanks.

Best,
Patrik

(Question) Fallback handling

Hi! I just got turned onto this library from the Awesome iOS mailing list. I think this library could help my current projects a ton!

One question, does Laurine handle fallbacks gracefully? For instance, if the phone's language is set to German, and a requested key is not in the German Localizable.strings file, will it fall back to using the Base language's value?

Support multi-line strings

My Localizable.strings contains

"Message" = "WTF\r\nWTF";

Laurine generates

    /// Base translation: WTF
WTF
    static var Message: String = "Message".localized

Swift Compiler Error Localizations.swift:64:1: Expected declaration

S3, S4 Support + Laurine Rework (announcement)

Since Apple is releasing Swift 4 sometime this fall, I will be going ahead and preparing a new version for it. This will also be a considerable overhaul of Laurine as I have few improvements in mind, most notably unit tests and rework of the script so it can be edited and worked on more easily, also performance updates for large files. The goal though is to preserve input or output, giving you no extra work, just replacing the Laurine file. Next version of Laurine should support both S3 and S4.

The important part is that it will also be reworked in a way where I can easily adapt it to support other file types as well (say, image assets) - My goal is to create few more projects based on Laurine where everything can use dot notation in a similar fashion, type safe, quickly.

I will be extending the list of stuff that needs to be done - if you have something you would like to see to be done over the holidays, don't hesitate to drop me a line here.

Sincerely,
Jiri

TBD:

  • Performance and extendability core rewrite

  • Unit Tests (File Parsing / Loading & CMD Line input)

  • Unit Tests (Properties)

  • Unit Tests (Method generation)

  • S3 Support

  • S4 Support

  • Add automatic support for frameworks

  • Fix issues with nesting and duplicities

  • Add debug log options

  • Pods Support

  • Carthage Support

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

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?

Keys as language keywords

Hello Jiri,

I coincidentally bumped into a problem where I used a key YES and apparently yes is also a keyword in Objective-C so a generated code could not compile. I suggest to use a key but with a prefix. Do you have any other/better solution?

Best,

Patrik

Swift 4 migration

Just tried to migrate a project to Swift 4 and it gives me an error on the Laurine build phase. Should probably be updated for Swift 4.

Swift 3 Support?

Any plans to update the project to swift 3?

If you need a hand just create a branch and I could help.

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.

How to use this with many languages?

Hello,
currently I have one language supported in app but soon I have to add another. How this script should be configured to support both languages without changes in code?

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.

"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.

Generated Localizations file is incomplete if input file contains certain characters

Spent some time today figuring out why out of 200+ strings Laurine generated localizations only for 17. Turned out it was caused by an illegal character at the end of one line which looks like normal space (I asked a colleague with Windows machine to translate the file for me):

let bad = " "
let good = " "

bad == good // false

print(bad.utf8.map { String($0, radix: 16) })  // ["c2", "a0"]
print(good.utf8.map { String($0, radix: 16) }) // ["20"]

I have no idea what this thing is, but it breaks NSDictionary(contentsOfFile:) on which Laurine relies to read the input file.

If the character is in the middle of string the result is nil, if it's in the end NSDictionary quietly fails to read further and returns what was read so far.

I used the latest version from master.

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

Compiled Script

Running LaurineGenerator.swift in the run phase takes about 5 seconds with my localization file (containing 460 strings).

When first compiling the script to an executable, the generation time only takes 0.25 seconds.

I know in the example project, the output is only generated if existing output is not newer than the localization input file. For the sake of having a clean and reproducible build, I prefer to skip that check and delete the generated files every time before running the script.

How could this project provide binaries?

What do you think?

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

Detect unused keys

It would be great if Laurine could help finding unused keys to make sure the Localizable.strings file can be kept clean over time. Before using Laurine I used a script to make sure keys not appearing in any NSLocalizedString would be deleted. But doing something similar with Laurine isn't possible as the command varies quite a lot (I'm using the dot-syntax leading to names like Localizations.Model.User.FirstName as an example – the key reads MODEL.USER.FIRST_NAME).

I'm not sure how this could be achieved, though I hope someone can come up with an idea. Maybe we could rework the resulting Swift file so that Xcode marks unused lines automatically with a warning (similar to unused variables)? Not sure if this is even possible. Would have to further investigate.

Any ideas?

"\\(variable)" not work

I have a code a bit like that

let count = liste.count
let formattedAmount = formatter.string(from: montant as NSNumber)!
let formattedDepense = formatter.string(from: depense as NSNumber)!
let formattedrevenu = formatter.string(from: revenu as NSNumber)!

            
let count = selectedRow.count
let str = Localizations.Listeoperation.Info(count)

in the file Localizable.strings (English)

"ListeOperation.info" = "%d opérations Dépenses : \(formattedDepense) Revenus : \(formattedrevenu) Solde : \(formattedAmount)";

and file Localizations.swift

 public struct Listeoperation {

        /// Base translation: %d opérations Dépenses : (formattedDepense) Revenus : (formattedrevenu) Solde : (formattedAmount)
        public static func Info(_ value1 : Int) -> String {
            return String(format: NSLocalizedString("ListeOperation.info", comment: ""), value1)
        }

    }

it does not work how could I do ??

"\(variable)" is not taken updated

Unable to run on El Capitan

I'm unable to run the package under El Capitan :(
getting this error:

<unknown>:0: error: no such file or directory: 'LaurineGenerator.swift'

Laurine's younger Sister - Image Generator [name pending]

Hello everyone,

I was thinking about making the same generator as Laurine for the image assets as well since the base is solid and resource generators that are available do not seem to do the job properly. It would work the same way, with similar options, through command-line or as build script - with a primary goal to generate nested result that you would use similarly as Laurine:

Localizations.Profile.Header vs Images.Profile.HeaderBar

There would also be a convenience to directly instantiate images (.image) or something similar, to get rid of UIImage(named: Images.Name) altogether.

What are your thoughts about that? Would you like something like this?

Have a great day,

Jiri

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

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!

Objc localization - String with format specifiers

Hi,
When I try to create the localization for Obj-C the script generates the following method:

/// Base translation: GO TO %@
- (NSString *(^)(NSString *))BenefitsGoToButtonTitle;

Is this the desired behaviour?
Best regards.

Unit Tests

Unit tests would be awesome. Any idea how to integrate them best? Create an OSX Xcode project with a test target? Or use Swift Package Manager?

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!

Not correct nested result

Not issue but add some warning would be good.
Localizable.strings

"profile.phone" = "Some title"
"profile.phone.number" = "Your phone number!"

Laurine will create without any warnings

                struct phone {

                                    /// Base translation: Your phone number!
                    static var number: String = "profile.phone.number".localized

                }

SwiftLint Violations

I just started using Laurine in a project that also uses SwiftLint to ensure code conventions. It appears that Laurines produced code does not comply to some conventions, for example I get this:

warning: Colon Violation: Colons should be next to the identifier when specifying a type. (colon)

Could we make the generated code comply to the Swift conventions expressed by https://github.com/realm/SwiftLint?

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?

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" = "";

Special characteres issue

Hi,

In my localization file I have an string like this:

reset-pass-label = "Enter your email address below and we'll \r\n send you a new password";

I used _\r\n_ because I need to break the line at that point, the problem is that the generated Swift file looks like this:

/// Base translation: Enter your email address below and we'll 
 send you a new password
    public static var ResetPassLabel : String = "reset-pass-label".localized

Somehow the break line is being applied to the source code as well, as a result the file does not compile.

Spaces not Replaced

Localized String Identifiers can have spaces in them.

"This is my localizable string" = "This is my localizable string"

This will result in the following generated code:

public static var This is my localizable string : String = "This is my localizable string".localized

Laurine should replace this whitespace characters with some safe character, like an underscore, or just remove it.

Laurine fails at -d parameter

Hi,
I've updated Laurine to the latest version in my project. However when I set up the script (inside Xcode build phases) then I've got this message:

PROJECT/PROJECT/Localization/Localizations.swift -c -d -
Invalid value(s) for option -d, --delimiter: 

Usage: /Users/xxx/PROJECT/PROJECT/Localization/LaurineGenerator.swift [options]
  -i, --input:
      Required | String | Path to the localization file
  -o, --outpu:
      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, --langu:
      Optional | String | [swift | objc] | Specifies language of generated output files | Defaults to [swift]
  -d, --delim:
      Optional | String | String delimiter to separate segments of each string | Defaults to [.]
  -c, --capit:
      Optional | Bool | When enabled, name of all structures / methods / properties are automatically CamelCased | Defaults to false
  -b, --baseC:
      Optional | String | Name of the base class | Defaults to "Localizations"
  -t, --strin:
      Optional | String | Name of strings table | Defaults to nil
  -s, --custo:
      Optional | String | A custom superclass name | Defaults to NSObject (only applicable in ObjC)
Command /bin/sh failed with exit code 64

This is my command to run Laurine:

"$LAURINE_PATH" -i "$SOURCE_PATH" -o "$OUTPUT_PATH" -c -d "-"

It does not work with -d "-" neither with -d -.
Do you know how to fix it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.