FlineDev / RemafoX

Report issues, request features or ask for help for the ReMafoX app here.
30 stars 1 forks source link

[Feat] Support SmallStrings #34

Open Sherlouk opened 2 years ago

Sherlouk commented 2 years ago

Problem Statement

SmallStrings is a two step process developed by EmergeTools with the goal of reducing the binary size impact of localisations.

https://github.com/EmergeTools/SmallStrings

Notably for ReMafoX is that it changes how you request a localisation - you can't simply use system APIs as this project currently does.

From a users perspective, nothing should change. Simply a reduction in binary size.

Suggested Solution

A new option would be added to the config file for whether a client would like to use SmallStrings.

If enabled, the enum file generated would change to remove the system APIs and only use the getter provided by SmallStrings. This is a small Swift script.

Additional Considerations

It's also be nice if this was done with support for #33 allowing for the enhanced compression and user chosen locale.

I'm happy to provide an example of what the output Swift enum should be if this would be helpful. This is the only required change. I can do this in the form of a sample app.

Jeehut commented 2 years ago

@Sherlouk Thank you for reporting this interesting features.

I never heard of SmallStrings and neither have I thought about reducing binary size by compressing localizations. I always expected images, videos and other assets to be the biggest concern when it comes to binary size, not texts like localization. While I will treat this as any other feature request – so I will prioritize based on upvotes and the "Size" label, I'd like to also understand this a bit better so I can focus on the right things if I happen to implement it. Could you please elaborate on why developers would want to use such a library? What needs make this kind of optimization necessary?

Thank you in advance for any insights. I'm curious to learn something new here!

Sherlouk commented 2 years ago

Of course the use case depends on the developer and their app. As you add more and more languages, and more and more localised strings, the size of these files can keep on growing.

With Apple adding binary size limits to some features (such as App Clips which requires the app be under 10MB), and simply the fact that we as developers should be encouraged to keep our apps small, leads us to look at cutting the size down wherever possible.

As you say, images, videos, fonts, and other assets are among the biggest concerns - however for large projects with lots of languages and strings, compressing and optimising in the way SmallStrings does leads to notable size savings (in the magnitude of saving 12MB for one of my projects!!)

I would also say as a developer using SmallStrings, it doesn't really add or impact how I handle translations currently. It's only since exploring ReMafoX which generates it's own type-safe enum that this is a consideration. Currently I use SwiftGen with my own stencil to handle this - I don't even notice the difference.

I suppose one option as a workaround is for me to simply not use the Swift file that ReMafoX generates - but this would be a shame as it's a valuable feature and does reduce complexity in the codebase.

Jeehut commented 2 years ago

@Sherlouk I see, thank you for the explanation.

I haven't had the time to check what SmallStrings is doing yet in detail, but if it turns out to not influence the workflow in Xcode and doesn't seem to have any downsides, I would even consider making it the default behavior in ReMafoX. I think it would be nice if all users of ReMafoX simply had the additional advantage of additionally saving some space in the binary.

But I will have to elaborate more before I can make any decisions. In any case, thank you for bringing this topic up!

Sherlouk commented 2 years ago

It's basically a two step process.

  1. A Run Script step which compresses and changes the format of the Localizable strings.
  2. A change to how you access localised strings in Swift (don't use system APIs).

Given ReMafoX already requires a Run Phase, it's potentially possible that you could do the compression yourself and require no changes by the end-user.

The changing of how you access the strings is relatively trivial - you can see a Swift example here of how to do it - though I rewrote this myself in my own app to be a bit cleaner and more efficient.

I have yet to find a downside to doing this. Small bit of work to set it up (though ReMafoX could automate it), and then just smaller bundle sizes. I don't believe it changes pluralisation dicts.

Jeehut commented 2 years ago

One downside seems to be the very fact that we would no longer be using system APIs and therefore any potential future changes or improvements might not work with this then. Not to say that this is a blocker for implementing it, but I think it's a blocker for making it the default behavior. I would make this optional then, leaving the decision to the users if they prefer using system APIs or smaller app binaries.

Thank you for the explanation and your quick answers!

Sherlouk commented 2 years ago

I think making it optional is the best move to start with. With support it'll make it trivial for clients to opt-in and start using it - in theory with zero code changes needed.

It should be possible to provide an estimated saving too by taking the file sizes of all string files combined, and comparing it to a compressed version (which you could do at runtime).

"Enable SmallStrings to reduce binary size by 13% (saving 1.4MB!)"