Skip to content
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
3 changes: 2 additions & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ jobs:
run: ./gradlew test
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: unitTestReports
path: |
TransifexNativeSDK/clitool/build/reports/tests/test/
TransifexNativeSDK/common/build/reports/tests/test/
TransifexNativeSDK/txsdk/build/reports/tests/
if-no-files-found: warn
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,43 @@ Context wrappedContext = TxNative.wrap(getApplicationContext());
wrappedContext.getString();
```

If you want to wrap the application context itself, you need to move the SDK's initialization from the application's `onCreate()` to `attachBaseContext()`:

```java
@Override
protected void attachBaseContext(Context base) {
// Initialize TxNative
String token = "<transifex_token>";

LocaleState localeState = new LocaleState(
base, // Use the base context instead of getApplicationContext()
// source locale
"en",
// supported locales
new String[]{"en", "el", "de", "fr", "ar", "sl", "es_ES", "es_MX"},
null);

TxNative.init(
// application context
base, // Use the base context instead of getApplicationContext()
// a LocaleState instance
localeState,
// token
token,
// cdsHost URL
null,
// a TxCache implementation
null,
// a MissingPolicy implementation
new AndroidMissingPolicy());

// Wrap the base application context
super.attachBaseContext(TxNative.wrap(base));
}
```

Note though that this global wrapper can interfere with third-party libraries that use their own string resources. In that case, use "AndroidMissingPolicy" so that these libraries have their strings translated.

If you want to disable the SDK functionality, don't initialize it and don't call any `TxNative` methods. `TxNative.wrap()` will be a no-op and the context will not be wrapped. Thus, all `getString()` etc methods, won't flow through the SDK.

## Cache
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.transifex.myapplication;

import android.app.Application;
import android.content.Context;
import android.content.Intent;

import com.transifex.txnative.LocaleState;
Expand All @@ -20,36 +21,50 @@ public void onCreate() {
// https://stackoverflow.com/questions/55265834/change-locale-not-work-after-migrate-to-androidx/58004553#58004553
// AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

// Start a service just for testing purposes
Intent serviceIntent = new Intent(this, SimpleIntentService.class);
SimpleIntentService.enqueueWork(this, serviceIntent);

// Uncomment to use strings as served by Android prefixed with "test: "
// TxNative.setTestMode(true);

// Uncomment, to disable styling of strings with HTML markup such as
// R.string.styled_text_not_escaped
// TxNative.setSupportSpannable(false);

// Fetch all translations from CDS
TxNative.fetchTranslations(null, null);
}

@Override
protected void attachBaseContext(Context base) {
// Initialize TxNative
String token = null;

// The app locales entered here should match the ones in `resConfigs` in gradle, so that
// multi locale support works for newer Androids.
LocaleState localeState = new LocaleState(getApplicationContext(),
LocaleState localeState = new LocaleState(base,
"en",
new String[]{"en", "el", "de", "fr", "ar", "sl"},
null);

TxNative.init(
getApplicationContext(), // application context
base, // application context
localeState, // a LocaleState instance
token, // token
null, // cdsHost URL
null, // a TxCache implementation
null); // a MissingPolicy implementation

// Uncomment to use strings as served by Android prefixed with "test: "
// TxNative.setTestMode(true);

// Uncomment, to disable styling of strings with HTML markup such as
// R.string.styled_text_not_escaped
// TxNative.setSupportSpannable(false);
// OPTIONAL:
// Wrap the application's base context to allow TxNative to intercept all string resource
// requests (e.g. from getApplicationContext().getString()).
// Warning: This global wrapper can interfere with third-party libraries that use their
// own string resources. Use "AndroidMissingPolicy" so that these libraries have their
// strings translated.
super.attachBaseContext(TxNative.wrap(base));

// Fetch all translations from CDS
TxNative.fetchTranslations(null, null);

// Start a service just for testing purposes
Intent serviceIntent = new Intent(this, SimpleIntentService.class);
SimpleIntentService.enqueueWork(this, serviceIntent);
// SAFER: Do not wrap the application's base context.
// super.attachBaseContext(base);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public static void enqueueWork(Context context, Intent work) {

@Override
protected void onHandleWork(@NonNull Intent intent) {
// Make sure that you use getBaseContext() and not getApplicationContext()
String success = getBaseContext().getResources().getString(R.string.success);
// Make sure that you do not use an app context via getApplicationContext().getString()
String success = getString(R.string.success);

Log.d(TAG, "Service status: " + success);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public NativeCore(@NonNull Context applicationContext,
@Nullable String cdsHost,
@Nullable TxCache cache,
@Nullable MissingPolicy missingPolicy) {
mContext = applicationContext.getApplicationContext();
mContext = applicationContext;
mMainHandler = new Handler(mContext.getMainLooper());
mLocaleState = localeState;
mLocaleState.setCurrentLocaleListener(mCurrentLocaleListener);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ public class TxNative {
private static NativeCore sNativeCore = null;

/**
* Initialize the SDK.
* Initialize the SDK. The method should only be called once.
* <p>
* Should be called in {@link Application#onCreate()}.
* Should be called in {@link Application#onCreate()} or
* {@link Application#attachBaseContext(Context)}.
* </p>
*
* @param applicationContext The application context.
Expand Down Expand Up @@ -63,6 +64,16 @@ public static void init(@NonNull Context applicationContext,
ViewPump.init(new TxInterceptor());
}

/**
* Checks if the SDK has been initialized by a previous call to
* {@link #init(Context, LocaleState, String, String, TxCache, MissingPolicy)}.
*
* @return <code>true</code> if the SDK has been initialized, <code>false</code> otherwise.
*/
public static boolean isInitialized() {
return sNativeCore != null;
}

/**
* When test mode is enabled, TransifexNative functionality is disabled: the translations provided
* by the SDK are not used. The original strings, as provided by Android's localization system,
Expand Down Expand Up @@ -158,9 +169,8 @@ public static void fetchTranslations(@Nullable String localeCode) {
* <p>
* <b>Warning: </b>You should use <code>getBaseContext()</code>, instead of
* <code>getApplicationContext()</code> when using string methods in services.

*
* @param context The activity context to wrap.
* @param context The context to wrap.
*
* @return The wrapped context.
*/
Expand All @@ -181,15 +191,9 @@ public static Context wrap(@NonNull Context context) {
/**
* Wraps a context to enable TransifexNative functionality in services and other scopes besides
* activities.
* <p>
* <b>Warning: </b>You should use <code>getBaseContext()</code>, instead of
* <code>getApplicationContext()</code> when using string methods in services.
* <p>
* Check out the installation guide regarding the usage of this method.
*
* @param context The service context to wrap.
*
* @return The wrapped context.
* @deprecated Use {@link #wrap(Context)} instead.
*/
@Deprecated
public static Context generalWrap(@NonNull Context context) {
Expand All @@ -201,6 +205,9 @@ public static Context generalWrap(@NonNull Context context) {
* that extends {@link androidx.appcompat.app.AppCompatActivity}.
* <p>
* This method should be called in {@link AppCompatActivity#getDelegate()}.
* <p>
* If your activity is extending {@link com.transifex.txnative.activity.TxBaseAppCompatActivity TxBaseAppCompatActivity}
* you don't have to call this method.
*
* @param delegate The activity's AppCompatDelegate.
* @param baseContext The activity's base context.
Expand Down
Loading