-
-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strings Catalogs migrated from .stringsdict don't work #26
Comments
It sounds like your Strings Catalog is a good stress-test for the tool 😄 That is strange though, you are right, the screenshot looks fine... Would you be able to pull the JSON for We can then put it into the fixture tests to try and replicate the issue... So far, this is what the tests are checking: xcstrings-tool/Tests/XCStringsToolTests/__Fixtures__/Substitution.xcstrings Lines 1 to 54 in 0c77774
|
Sure, here it goes, paste it to your file and test it out :)"common.feed.translations_seen_by" : {
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "مشاهدة الترجمة من قبل %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"few" : {
"stringUnit" : {
"state" : "translated",
"value" : "%a أولياء أمور"
}
},
"many" : {
"stringUnit" : {
"state" : "translated",
"value" : "%a ولي أمر"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "ولي أمر واحد (%a)"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%a ولي أمر"
}
},
"two" : {
"stringUnit" : {
"state" : "translated",
"value" : "وليا أمر (%a)"
}
},
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "%a ولي أمر"
}
}
}
}
}
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traducció vista per %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pare"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pares"
}
}
}
}
}
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Übersetzung gesehen von %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg Elternteil"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg Eltern"
}
}
}
}
}
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Translation viewed by %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parents"
}
}
}
}
}
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Translation viewed by %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parents"
}
}
}
}
}
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traducción vista por %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg padre"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg padres"
}
}
}
}
}
}
},
"es-ES" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traducción vista por %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg padre"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg padres"
}
}
}
}
}
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ang pagsasalin ay tiningnan ng %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg magulang"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg magulang"
}
}
}
}
}
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traduction vue par %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parents"
}
}
}
}
}
}
},
"fr-CA" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traduction vue par %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg parents"
}
}
}
}
}
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "अनुवाद को %#@number_of_parents@ अभिभावकों द्वारा देखा गया"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg अभिभावक"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg अभिभावक"
}
}
}
}
}
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terjemahan dilihat oleh %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg orang tua"
}
}
}
}
}
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Traduzione visualizzato da %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg genitore"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg genitori"
}
}
}
}
}
}
},
"ja-JP" : {
"stringUnit" : {
"state" : "translated",
"value" : "%#@number_of_parents@ 人が翻訳を閲覧"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg人の保護者"
}
}
}
}
}
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "학부모 %#@number_of_parents@ 명 번역 읽음"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "학부모 %arg명"
}
}
}
}
}
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terjemahan dilihat oleh %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg ibu bapa"
}
}
}
}
}
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Vertaling door %#@number_of_parents@ ouder(s) bekeken"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "new",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "new",
"value" : "%arg parents"
}
}
}
}
}
}
},
"pa-Arab-PK" : {
"stringUnit" : {
"state" : "translated",
"value" : " ولوں ترجمہ ویکھیا گیا%#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "new",
"value" : "%arg parent"
}
},
"other" : {
"stringUnit" : {
"state" : "new",
"value" : "%arg parents"
}
}
}
}
}
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tłumaczenie wyświetlone przez %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"few" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg rodziców"
}
},
"many" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg rodziców"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg rodzic"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg rodziców"
}
}
}
}
}
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tradução visualizada por %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pai/mãe"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pais"
}
}
}
}
}
}
},
"pt-PT" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tradução vista por %#@number_of_parents@"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pai/mãe"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg pais/mães"
}
}
}
}
}
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "%#@number_of_parents@ просмотрели перевод"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"few" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg родителей"
}
},
"many" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg родителей"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg родитель"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg родителей"
}
}
}
}
}
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "มีผู้ดูคำแปลแล้ว %#@number_of_parents@ คน"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "ผู้ปกครอง %arg คน"
}
}
}
}
}
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tercüme %#@number_of_parents@ tarafından görütülendi"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg veli"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg veli"
}
}
}
}
}
}
},
"ur-PK" : {
"stringUnit" : {
"state" : "translated",
"value" : "%#@number_of_parents@ نے ترجمہ دیکھا"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg والد/والدہ"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg والدین"
}
}
}
}
}
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Bài dịch đã được %#@number_of_parents@ phụ huynh xem "
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg phụ huynh "
}
}
}
}
}
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "%#@number_of_parents@ 查看了译文"
},
"substitutions" : {
"number_of_parents" : {
"formatSpecifier" : "ld",
"variations" : {
"plural" : {
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%arg 名家长"
}
}
}
}
}
}
}
}
} |
Great, thanks! From a quick glance, it looks like |
Ahh, that makes sense.. .stringsdict required that you had a single substitution (purple) whereas .xcstrings seems to support one plural without the substitution syntax. I created a .stringsdict file that replicates a few valid scenarios: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>fromStringsDictionary</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>There %#@number_of_substitutions@ in this phrase</string>
<key>number_of_substitutions</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>are no substitutions</string>
<key>one</key>
<string>is %lld substitution</string>
<key>other</key>
<string>are %lld substitutions</string>
</dict>
</dict>
<key>fromStringsDictionaryWithArg</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@! There %#@number_of_substitutions@ in this phrase</string>
<key>number_of_substitutions</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>are no substitutions</string>
<key>one</key>
<string>is %lld substitution</string>
<key>other</key>
<string>are %lld substitutions</string>
</dict>
</dict>
<key>fromStringsDictionaryWithPositionalArgs</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%2$@! There %1$#@number_of_substitutions@ in this phrase</string>
<key>number_of_substitutions</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>are no substitutions</string>
<key>one</key>
<string>is %lld substitution</string>
<key>other</key>
<string>are %lld substitutions</string>
</dict>
</dict>
</dict>
</plist> func testStringsDictionary() throws {
let bundle = Bundle.module
XCTAssertEqual(
String(format: bundle.localizedString(forKey: "fromStringsDictionary", value: nil, table: "Migration"), 0),
"There are no substitutions in this phrase"
)
XCTAssertEqual(
String(format: bundle.localizedString(forKey: "fromStringsDictionaryWithArg", value: nil, table: "Migration"), "John", 10),
"John! There are 10 substitutions in this phrase"
)
XCTAssertEqual(
String(format: bundle.localizedString(forKey: "fromStringsDictionaryWithPositionalArgs", value: nil, table: "Migration"), 1, "John"),
"John! There is 1 substitution in this phrase"
)
} Using the migrator, this gives me the following Strings Catalog: {
"sourceLanguage" : "en",
"strings" : {
"fromStringsDictionary" : {
"extractionState" : "migrated",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "There %#@number_of_substitutions@ in this phrase"
},
"substitutions" : {
"number_of_substitutions" : {
"formatSpecifier" : "lld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "is %arg substitution"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "are %arg substitutions"
}
},
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "are no substitutions"
}
}
}
}
}
}
}
}
},
"fromStringsDictionaryWithArg" : {
"extractionState" : "migrated",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "%@! There %#@number_of_substitutions@ in this phrase"
},
"substitutions" : {
"number_of_substitutions" : {
"formatSpecifier" : "lld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "is %arg substitution"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "are %arg substitutions"
}
},
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "are no substitutions"
}
}
}
}
}
}
}
}
},
"fromStringsDictionaryWithPositionalArgs" : {
"extractionState" : "migrated",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "%2$@! There %#@number_of_substitutions@ in this phrase"
},
"substitutions" : {
"number_of_substitutions" : {
"argNum" : 1,
"formatSpecifier" : "lld",
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "is %lld substitution"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "are %lld substitutions"
}
},
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "are no substitutions"
}
}
}
}
}
}
}
}
}
},
"version" : "1.0"
} So
This means that we should not assume that it will be defined. The only reason that we require it anyway is to use the substitution key as the label for the argument.. I'll have a play around to see how to relax this a bit 👍 |
Hey @liamnichols !
I downloaded your demo project DogTracker to test things out, and replaced the
Localizable.xcstrings
with our own (we have a lot of languages, and a lot of strings - the file itself has 12MB and ~600 000 lines).When compiling the dog Tracker, error is shown:
Decoding error at ‘strings → common.feed.translations_seen_by → localizations → ar → substitutions → number_of_parents‘ - The data couldn’t be read because it is missing.
As you can see on the screenshot, everything looks correct. I wonder if you are able to debug this issue. Note: It is using 0.1.1 version released 30 mins ago. :)
The text was updated successfully, but these errors were encountered: