Crowdin Android SDK delivers all new translations from Crowdin project to the application immediately. So there is no need to update this application via Google Play Store to get the new version with the localization.
The SDK provides:
- Over-The-Air Content Delivery – the localized files can be sent to the application from the project whenever needed
- Real-time Preview – all the translations that are done via Crowdin Editor can be shown in the application in real-time
- Screenshots – all screenshots made in the application may be automatically sent to your Crowdin project with tagged source strings
- Requirements
- Installation
- Setup
- Advanced Features
- Parameters
- File Export Patterns
- Notes
- Limitations
- Contribution
- Seeking Assistance
- Security
- License
- Android SDK version 16+
-
JCenter
implementation 'com.crowdin.platform:mobile-sdk:1.1.2'
-
Download or clone this module.
To configure Android SDK integration you need to:
- Set up Distribution in Crowdin.
- Set up SDK and enable Over-The-Air Content Delivery feature using Android Studio.
Distribution is a CDN vault that mirrors the translated content of your project and is required for integration with Android app.
To manage distributions open the needed project and go to Over-The-Air Content Delivery. You can create as many distributions as you need and choose different files for each. You’ll need to click the Release button next to the necessary distribution every time you want to send new translations to the app.
Note: currently, Custom Languages, Dialects, and Language Mapping are not supported for Android SDK.
To integrate SDK with your application you need to follow step by step instructions:
-
Inject Crowdin translations by adding override method in BaseActivity class to inject Crowdin translations into the Context.
Note: If you don’t have BaseActivity class add the code to all of your activities.
Kotlin
override fun attachBaseContext(newBase: Context) { super.attachBaseContext(Crowdin.wrapContext(newBase)) }
Java
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(Crowdin.wrapContext(newBase)); }
In case your project already overrides attachBaseContext use the following code:
@Override super.attachBaseContext(Crowdin.wrapContext(SomeLib.wrap(newBase)));
SKD uses
androidx
version of libraries. In case your project still not migrated toandroidx
you can add this lines in thegradle.properties
file:android.enableJetifier=true android.useAndroidX=true
It might require additional changes in your code.
-
Enable Over-The-Air Content Delivery in your Crowdin project so that application can pull translations from CDN vault. Add the following code to App/Application class:
Kotlin
override fun onCreate() { super.onCreate() Crowdin.init(applicationContext, CrowdinConfig.Builder() .withDistributionHash(your_distribution_hash) // required .withNetworkType(network_type) // optional .withRealTimeUpdates() // optional .withScreenshotEnabled() // optional .withSourceLanguage(source_language) // optional .withUpdateInterval(interval_in_milisec) // optional .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) // optional .build()) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Crowdin.init(this, new CrowdinConfig.Builder() .withDistributionHash(your_distribution_hash) // required .withNetworkType(network_type) // optional .withRealTimeUpdates() // optional .withScreenshotEnabled() // optional .withSourceLanguage(source_language) // optional .withUpdateInterval(interval_in_milisec) // optional .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) // optional .build()); }
your_distribution_hash
- when distribution added you will get your unique hash.network_type
- optional. Acceptable values areNetworkType.ALL
,NetworkType.CELLULAR
,NetworkType.WIFI
;source_language
- source language in your Crowdin project. Example -"en"
. Required for Screenshots and Real-Time Preview features.interval_in_milisec
- translations update interval in milliseconds.client_id
,client_secret
- Crowdin OAuth Client ID and Client Secret.organization_name
- Organization domain name (for Crowdin Enterprise users only).
This feature allows translators to see translations in the application in real-time. It can also be used by managers and QA team to preview translations before release.
-
Add the following code to the Application class:
Kotlin
Crowdin.init(applicationContext, CrowdinConfig.Builder() ... .withRealTimeUpdates() .withSourceLanguage(source_language) .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) ...)
Java
Crowdin.init(this, new CrowdinConfig.Builder() ... .withRealTimeUpdates() .withSourceLanguage(source_language) .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) ...);
-
Crowdin Authorization is required for Real-Time Preview feature. Create connection using Activity/Fragment method inMainActivity class:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { Crowdin.authorize(this) }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); Crowdin.authorize(this); }
Note: tt will redirect to Crowdin OAuth form and after authorization download all required data automatically.
You can disconnect via:
override fun onDestroy() {
super.onDestroy()
// Close connection with Crowdin.
Crowdin.disconnectRealTimeUpdates()
}
Enable if you want all the screenshots made in the application to be automatically sent to your Crowdin project with tagged strings. This will provide additional context for translators. You can use system buttons to a take screenshot and automatically upload them to Crowdin or you can create your own handler (for example, clicking on some button in your application).
-
Add the following code to the Application class:
Kotlin
Crowdin.init(applicationContext, CrowdinConfig.Builder() ... .withScreenshotEnabled() .withSourceLanguage(source_language) .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) ...) // Using system buttons to take screenshot automatically will upload them to Crowdin. Crowdin.registerScreenShotContentObserver(this)
Java
Crowdin.init(this, new CrowdinConfig.Builder() ... .withScreenshotEnabled() .withSourceLanguage(source_language) .withAuthConfig(AuthConfig(client_id, client_secret, organization_name)) .build()); // Using system buttons to take screenshot automatically will upload them to Crowdin. Crowdin.registerScreenShotContentObserver(this);
Note: using
Crowdin.registerScreenShotContentObserver(this)
(system buttons handler) for sending screenshots to Crowdin requires Storage permission for your app. -
Crowdin Authorization is required for screenshots. Create connection using Activity/Fragment method in MainActivity class:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { Crowdin.authorize(activity) }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); Crowdin.authorize(this); }
-
After auth success you can use system buttons to capture screenshots or do it programmatically with callback:
Kotlin
Crowdin.sendScreenshot(activity!!, object : ScreenshotCallback { override fun onSuccess() { Log.d(TAG, "Screenshot uploaded") } override fun onFailure(throwable: Throwable) { Log.d(TAG, throwable.localizedMessage) } })
Java
View.OnClickListener oclBtnOk = new View.OnClickListener() { @Override public void onClick(View v) { Crowdin.sendScreenshot(YourActivity.this, new ScreenshotCallback() { @Override public void onSuccess() { Log.d("", "Screenshot uploaded"); } @Override public void onFailure(Throwable throwable) { Log.d("", String.valueOf(throwable)); } }); } };
Required for all features | |
your_distribution_hash | Unique hash which you can get by going to Over-The-Air Content Delivery in your project settings. To see the distribution hash open the needed distribution, choose Edit and copy distribution hash |
Required for advanced features | |
source_language | Source language in your Crowdin project (e.g. "en") |
client_id; client_secret | Crowdin authorization credentials. Open the project and go to Over-The-Air Content Delivery, choose the feature you need and click Get Credentials |
Optional | |
network_type | Network type to be used. You may select NetworkType.ALL , NetworkType.CELLULAR , or NetworkType.WIFI |
interval_in_milisec | Translations update intervals in milliseconds. Allowed values - from 15 minutes. If not set - translations in an application will be updated once per application load. |
You can set file export patterns and check existing ones using File Settings. The following placeholders are supported:
Name | Description |
---|---|
%language% | Language name (e.g. Ukrainian) |
%two_letters_code% | Language code ISO 639-1 (e.g. uk) |
%three_letters_code% | Language code ISO 639-2/T (e.g. ukr) |
%locale% | Locale (e.g. uk-UA) |
%locale_with_underscore% | Locale (e.g. uk_UA) |
%android_code% | Android Locale identifier used to name "values-" directories |
-
You can provide new Strings
Load your Strings in any way / any time / any place and just call this:
Crowdin.setStrings(language, newStrings); // e.g. language="en" newStrings=map of (key-value)s
-
Please note that Crowdin works with current locale, so if you change locale with
Locale.setDefault(newLocale);
Crowdin will start using strings of the new locale.
-
For displaying a string, Crowdin tries to find that in dynamic strings, and will use bundled version as fallback. In the other words, Only the new provided strings will be overridden and for the rest the bundled version will be used.
-
To translate menu items you need to update your
onCreateOptionsMenu
method:override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflateWithCrowdin(R.menu.activity_menu, menu, resources) return true }
@Override public boolean onCreateOptionsMenu(Menu menu) { ExtentionsKt.inflateWithCrowdin(getMenuInflater(), R.menu.your_menu, menu, getResources()); return true; }
-
In case you have custom views that uses
TypedArray
andstylable
attributes, you will need to use such approach:val textId = typedArray.getResourceId(R.styleable.sample_item, 0) textView.setText(textId)
instead of
typedArray.getString(R.styleable.sample_item)
-
Activity title defined via AndroidManifest won't be translated.
<activity android:name=".activities.SampleActivity" android:label="@string/title"/>
You can simply update your
toolbar
inside of activity or fragment:toolbar.setTitle(R.string.title);
-
In case your project already overrides
attachBaseContext
:super.attachBaseContext(Crowdin.wrapContext(SomeLib.wrap(newBase)));
-
You can register/unregister observer for data changes by adding this lines:
override fun onCreate(savedInstanceState: Bundle?) { // Observe data loading. Crowdin.registerDataLoadingObserver(this) }
-
ShakeDetector for triggering force upload from Crowdin. It will try to download latest updates from release.
override fun onCreate(savedInstanceState: Bundle?) { // Simple device shake detector. Could be used for triggering force update. Crowdin.registerShakeDetector(this) }
On each shake event it will trigger this method:
Crowdin.forceUpdate(this)
You can call this method from your app. Also there are other public methods inCrowdin
class. You can find details inkotlin doc
files.
- Plurals are supported from Android SDK version 24.
- TabItem text added via xml won't be updated. There is workaround: you can store tabItem titles in your string-array and add tabs dynamically.
PreferenceScreen
defined via XML not supported.
We are happy to accept contributions to the Crowdin Android SDK. To contribute please do the following:
- Fork the repository on GitHub.
- Decide which code you want to submit. Commit your changes and push to the new branch.
- Ensure that your code adheres to standard conventions, as used in the rest of the library.
- Ensure that there are unit tests for your code.
- Submit a pull request with your patch on Github.
If you find any problems or would like to suggest a feature, please feel free to file an issue on Github at Issues Page.
Need help working with Crowdin Android SDK or have any questions? Contact Customer Success Service.
Crowdin Android SDK CDN feature is built with security in mind, which means minimal access possible from the end-user is required. When you decide to use Crowdin Android SDK, please make sure you’ve made the following information accessible to your end-users.
- We use the advantages of Amazon Web Services (AWS) for our computing infrastructure. AWS has ISO 27001 certification and has completed multiple SSAE 16 audits. All the translations are stored at AWS servers.
- When you use Crowdin Android SDK CDN – translations are uploaded to Amazon CloudFront to be delivered to the app and speed up the download. Keep in mind that your users download translations without any additional authentication.
- We use encryption to keep your data private while in transit.
- We do not store any Personally Identifiable Information (PII) about the end-user, but you can decide to develop the opt-out option inside your application to make sure your users have full control.
- The Automatic Screenshots and Real-Time Preview features are supposed to be used by the development team and translators team. Those features should not be compiled to the production version of your app. Therefore, should not affect end-users privacy in any way.
Copyright © 2020 Crowdin The Crowdin Android SDK is licensed under the MIT License. See the LICENSE file distributed with this work for additional information regarding copyright ownership. Except as contained in the LICENSE file, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.