Skip to content

Commit

Permalink
Full String Catalog support
Browse files Browse the repository at this point in the history
With the introduction of the String Catalogs file format in Xcode 15,
developers have now the option to create localizations that vary by
device and/or by plural. On top of that, multiple tokens can be added in
a localized phrase (also known as substitutions) that can also support
the aforementioned variations.

In order to support all those new formats as well as the old
substitution rules found in the Strings Dictionary format
(`.stringsdict`), the advanced rules from the CLI tool are formatted as
an intermediate XML structure and pushed to CDS.

Once those XML structures are pulled from CDS by the application, they
need to be properly parsed and formatted in a way so that they are ready
for presentation when needed by the application. During the phase when
the SDK populates its cache, the XML structures are either evaluated
based on the device that they currently run (in case of device
variations) or they are converted to intermediate ICU rules (if they
contain plural variations) so that they are ready to be evaluated when
arguments are passed to them during runtime.

For that to happen, the logic that devices the plural rule extraction
has been heavily refactored to account for all possible cases (simple
plural rules, multiple plural rules, plural rules with extra arguments,
and so on), while making sure that the right argument is used on the
right rule by respecting the positional specifiers on each substitution
phrase.

More unit tests have been added to test those cases as well as edge-case
scenarios and existing unit tests have been improved.
  • Loading branch information
stelabouras committed May 29, 2024
1 parent 4490b3e commit 030439d
Show file tree
Hide file tree
Showing 5 changed files with 1,039 additions and 56 deletions.
29 changes: 28 additions & 1 deletion Sources/Transifex/Cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,34 @@ public final class TXDiskCacheProvider: NSObject, TXCacheProvider {
return nil
}

return storedTranslations
return filterXMLPlurals(storedTranslations)
}

// Process XML stored translations (device variations, substitutions, etc).
private static func filterXMLPlurals(_ translations: TXTranslations?) -> TXTranslations? {
guard var translations = translations else {
return nil
}
for (localeKey, localeStrings) in translations {
for (sourceStringKey, stringInfo) in localeStrings {
guard let sourceString = stringInfo[TXDecoratorCache.STRING_KEY] else {
continue
}
// Detect if the string begins with the CDS root XML tag:
// `<cds-root>`
if (!sourceString.hasPrefix("<\(TXNative.CDS_XML_ROOT_TAG_NAME)>")) {
continue
}
// Process it and synthesize the final rule.
guard let processedString = XMLPluralParser.extract(pluralString: sourceString) else {
Logger.error("\(#function) Error attempting to extract source string with key \(sourceStringKey)")
continue
}
// Replace the source string with the processed value
translations[localeKey]?[sourceStringKey]?[TXDecoratorCache.STRING_KEY] = processedString
}
}
return translations
}

public func getTranslations() -> TXTranslations? {
Expand Down
14 changes: 13 additions & 1 deletion Sources/Transifex/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,19 @@ public final class TXNative : NSObject {

/// The filename of the file that holds the translated strings and it's bundled inside the app.
public static let STRINGS_FILENAME = "txstrings.json"


/// XML name to be used for the root XML element when the pluralization rule is not supported by CDS
/// and has to be uploaded as XML instead of the ICU format.
public static let CDS_XML_ROOT_TAG_NAME = "cds-root"

/// XML name to be used for the child XML elements when the pluralization rule is not supported by
/// CDS and has to be uploaded as XML instead of the ICU format.
public static let CDS_XML_TAG_NAME = "cds-unit"

/// XML attribute to be used in the CDS_XML_TAG_NAME elements when the pluralization rule is not
/// supported by CDS and has to be uploaded as XML instead of the ICU format.
public static let CDS_XML_ID_ATTRIBUTE = "id"

/// An instance of the core class that handles all the work
private static var tx : NativeCore?

Expand Down
Loading

0 comments on commit 030439d

Please sign in to comment.