liamnichols / xcstrings-tool

A plugin to generate Swift constants for your Strings Catalogs.
https://swiftpackageindex.com/liamnichols/xcstrings-tool/documentation/documentation
MIT License
134 stars 24 forks source link

String containing a single `%` is parsed incorrectly #63

Closed liamnichols closed 3 weeks ago

liamnichols commented 3 weeks ago

Given the following:

Screenshot 2024-05-06 at 10 27 18

The current code generates as so:

/// A fixed string containing the % symbol
public static func percentageDiscount(_ arg1: UInt) -> Self {
    Self (
        key: "percentageDiscount",
        defaultValue: ###"50\###(arg1)ff"###,
        table: "Localizable",
        locale: .current,
        bundle: .current
    )
}

But this is wrong, it should be:

public static var percentageDiscount: Self {
    Self (
        key: "percentageDiscount",
        defaultValue: ###"50% off"###,
        table: "Localizable",
        locale: .current,
        bundle: .current
    )
}
liamnichols commented 3 weeks ago

I think a couple of things to note here:

  1. A single % needs to be ignored
  2. A double %% also needs to be ignored

But additionally, this has exposed some interesting behaviour with the new foundation APIs...

When using String.init(format:), to use a single % it needs to be escaped as %% as demonstrated here:

String(format: "50%% off") // 50% off
String(format: "50% off")  // 500ff

It seems that String.init(localized:...) will use String.init(format:) if there are other arguments in the string, otherwise it won't, so it means that you need to escape the % only if your string has other arguments. The correct way is like so:

Screenshot 2024-05-06 at 17 57 33

In the future, we could probably add some diagnostics to help flag this, but for now, we probably just want to make sure that we don't mistake % or %% as a format specifier.