Skip to content
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

Release: 1.0.3 #49

Merged
merged 4 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ on:
jobs:
build:

runs-on: macos-latest
runs-on: macos-12

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Build
run: swift build -v
- name: Run tests
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ key if the entry is not found.

- Adds method to activate SDK from a Swift Package.
- Adds reference to SwiftUI limitation in README.

## Transifex iOS SDK 1.0.3

*December 27, 2022*

- Fixes TXPreferredLocaleProvider so that it uses the correct language candidate
based on user's preference and supported languages by the app developer.
- Fixes deprecation warnings on Github action.
2 changes: 1 addition & 1 deletion Sources/Transifex/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ render '\(stringToRender)' locale code: \(localeCode) params: \(params). Error:
/// A static class that is the main point of entry for all the functionality of Transifex Native throughout the SDK.
public final class TXNative : NSObject {
/// The SDK version
internal static let version = "1.0.2"
internal static let version = "1.0.3"

/// The filename of the file that holds the translated strings and it's bundled inside the app.
public static let STRINGS_FILENAME = "txstrings.json"
Expand Down
57 changes: 43 additions & 14 deletions Sources/Transifex/Locales.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,23 @@ public protocol TXCurrentLocaleProvider {
func currentLocale() -> String
}

/// Class that returns the language code of the current user's locale and falls back to "en" if the language
/// code cannot be found.
/// Class that returns the active language code that can be used for localization, based on the current user's
/// language preferences and the locales that the application supports. The class falls back to "en" if the
/// language code cannot be found.
public final class TXPreferredLocaleProvider : NSObject {
private static let FALLBACK_LOCALE = "en"
private var _appLocales : [String]
private var _currentLocale : String

override init() {
/// Designated initializer.
///
/// - Parameter appLocales: The locales the the application supports.
init(_ appLocales: [String]) {
_appLocales = appLocales

// Fetch the current locale on initialization and return it when it's
// requested by the `currentLocale()` method.
_currentLocale = TXPreferredLocaleProvider.getCurrentLocale()
_currentLocale = Self.getCurrentLocale(_appLocales)

super.init()

Expand All @@ -38,18 +46,33 @@ public final class TXPreferredLocaleProvider : NSObject {

@objc
private func currentLocaleDidChange() {
_currentLocale = TXPreferredLocaleProvider.getCurrentLocale()
_currentLocale = Self.getCurrentLocale(_appLocales)
}

private static func getPreferredLocale() -> Locale {
guard let preferredIdentifier = Locale.preferredLanguages.first else {
if let preferredLanguage = Locale.preferredLanguages.first {
return Locale(identifier: preferredLanguage)
}
else {
return Locale.autoupdatingCurrent
}
return Locale(identifier: preferredIdentifier)
}

private static func getCurrentLocale() -> String {
return getPreferredLocale().languageCode ?? "en"
private static func getCurrentLocale(_ appLocales: [String]) -> String {
// Attempt to get the most preferred locale based on:
// * the supported app locales provided by the developer when
// initializing the TXNative instance.
// * the preferred languages set by the user in the device Settings.
if let preferredLocalization = Bundle.preferredLocalizations(from: appLocales,
forPreferences: Locale.preferredLanguages).first {
return preferredLocalization
}
// Although it's highly unlikely that a preferred localization will not
// be extracted using the preferredLocalizations() call, we have a
// number of fallbacks in place to locate the best candidate.
else {
return getPreferredLocale().languageCode ?? FALLBACK_LOCALE
}
}
}

Expand Down Expand Up @@ -113,13 +136,19 @@ public final class TXLocaleState : NSObject {
// Make sure we filter all duplicate values
// by converting the array to a Set.
var distinctAppLocales = Set(appLocales)
// Insert the source locale in case it hasn't been added.
distinctAppLocales.insert(sourceLocale)
self.appLocales = Array(distinctAppLocales)
// Remove the source locale (if it has been already added by the
// developer).
distinctAppLocales.remove(sourceLocale)

self.translatedLocales = self.appLocales.filter { $0 != sourceLocale }
self.translatedLocales = Array(distinctAppLocales)

self.appLocales = Array(distinctAppLocales)
// Add the source locale as the first element of the array, as the
// `TXPreferredLocaleProvider` (and `Bundle.preferredLocalizations` more
// specifically) uses the first element as a fallback.
self.appLocales.insert(sourceLocale, at: 0)

self.currentLocaleProvider = currentLocaleProvider ?? TXPreferredLocaleProvider()
self.currentLocaleProvider = currentLocaleProvider ?? TXPreferredLocaleProvider(self.appLocales)
}

/// Returns true if the given locale is the source locale, false otherwise.
Expand Down
37 changes: 32 additions & 5 deletions Tests/TransifexTests/TransifexTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -572,22 +572,47 @@ final class TransifexTests: XCTestCase {
XCTAssertEqual(result, "ERROR")
}

func testCurrentLocale() {
func testCurrentLocaleNotFirstPreference() {
let appleLanguagesKey = "AppleLanguages"
let storedLanguages = UserDefaults.standard.value(forKey: appleLanguagesKey)

UserDefaults.standard.set([ "el" ],
UserDefaults.standard.set([ "nl", "fr" ],
forKey: appleLanguagesKey)

let locale = TXLocaleState(appLocales: [])
let locale = TXLocaleState(sourceLocale: "en",
appLocales: [ "fr", "de", "es", "it"])

XCTAssertEqual(locale.currentLocale,
"el")
"fr")

UserDefaults.standard.set(storedLanguages,
forKey: appleLanguagesKey)
}

func testCurrentLocaleNotAnyPreference() {
let appleLanguagesKey = "AppleLanguages"
let storedLanguages = UserDefaults.standard.value(forKey: appleLanguagesKey)

UserDefaults.standard.set([ "nl", "fr" ],
forKey: appleLanguagesKey)

let locale = TXLocaleState(sourceLocale: "en",
appLocales: [ "de", "es", "it"])

XCTAssertEqual(locale.currentLocale,
"en")

UserDefaults.standard.set(storedLanguages,
forKey: appleLanguagesKey)
}

func testSourceLocalePosition() {
let locale = TXLocaleState(sourceLocale: "en",
appLocales: [ "fr", "el" ])

XCTAssertTrue(locale.appLocales.first == "en")
}

func testTranslateWithSourceStringsInCache() {
let sourceLocale = "en"
let localeState = TXLocaleState(sourceLocale: sourceLocale,
Expand Down Expand Up @@ -661,7 +686,9 @@ final class TransifexTests: XCTestCase {
("testPlatformStrategyWithInvalidSourceString", testPlatformStrategyWithInvalidSourceString),
("testErrorPolicy", testErrorPolicy),
("testErrorPolicyException", testErrorPolicyException),
("testCurrentLocale", testCurrentLocale),
("testCurrentLocaleNotFirstPreference", testCurrentLocaleNotFirstPreference),
("testCurrentLocaleNotAnyPreference", testCurrentLocaleNotAnyPreference),
("testSourceLocalePosition", testSourceLocalePosition),
("testTranslateWithSourceStringsInCache", testTranslateWithSourceStringsInCache),
]
}