Code Monkey home page Code Monkey logo

lingver's Introduction

Lingver

Lingver is a library to manage your application locale and language.

Once you set a desired locale, Lingver will enforce your application to provide correctly localized data via Resources class.

The library contains an implementation of the approach described in the following blogpost.

Setup

The setup is pretty simple:

  1. Initialize the library in Application.onCreate:
Lingver.init(context, defaultLanguage)

See the sample app for more customization options.

  1. Change a locale, for instance, from your setting screen:
 Lingver.getInstance().setLocale(context, language)

Note that you need to update all already fetched locale-based data manually. Lingver is not responsible for that.

Follow the system locale

You can configure Lingver to follow the system locale whenever it changes:

 Lingver.getInstance().setFollowSystemLocale(context)

Note that any call to setLocale() stops following the system locale and resets isFollowingSystemLocale() setting.

WebView

Starting from Android N, there is a weird side effect while using a WebView in your application. For unknown reasons, the very first creation of it (either programmatically or via inflation) resets an application locale to the system default. Obviously, this is not what we expect to happen. Moreover, it's not going to be fixed anytime in the future according to the issuetracker. That's why we should somehow deal with it on our own.

There are plenty of ways how we can fix that, but the idea stays always the same. You have to set back the desired locale after the first usage of a WebView. For instance, you can even programmatically create a fake WebView and immediately set a locale back which prevents this side effect from happening in the future. See an example of implementation in the sample app.

App Bundles

While using an app bundle, a user’s device only downloads string resources that match the one or more languages currently selected in the device’s settings. Refer to this page if you want to change this behavior and have access to additional language resources.

Download

repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    implementation "com.github.YarikSOffice:lingver:1.3.0"
}

License

The MIT License (MIT)

Copyright 2019 Yaroslav Berezanskyi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

lingver's People

Contributors

rumataestorish avatar yariksoffice avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lingver's Issues

Android 5.1.1 language change not working

Hi, i implemented language change on my app, everything works fine but i received report about problem on Android 5.1, on this version is language change do nothing, just refresh activity and whole content remain in default language.

Does anybody face similar issue ? or this version and lower are not supported ?
Thanks upfront for any help :)

Does not work good with AAB instead of APK

I just discovered on a device by Xiaomi with MIUI12 that translations may be missing if you publish the app on Google Play as AAB (Android App Bundle). After changing to the traditional APK everything was OK. I believe, when using AAB Google Play only installs the language which is used by the device - as the idea of AAB is to save storage space.

Maybe this should be mentioned in the documentation.

На некоторых устройствах в некоторых местах текст не меняется

Здравствуйте
Я использую вашу библиотеку в своем приложении, но на некоторых устройствах в некоторых местах текст не меняется. В этих устройствах всё хорошо работает, если полностью закрою приложение и заново в него войду. У себя в проекте я использую библиотеку Conductor вместо фрагментов. Мы про тестировали это на нескольких устройствах. Могу скинуть скриншоты и марку телефонов на которых оно проявляется.

Код Application класса как я инициализироваю Lingver:

@Override
    public void onCreate() {
        super.onCreate();
        Lingver.init(this, new PreferencesHelper(this, new Gson()).getLocale()); 
}

Это код после смены языка пользователем:

@Override
    public void changeLanguage(@NotNull String lang) {
        Lingver.getInstance().setLocale(binding.getRoot().getContext(), lang);
        getActivity().recreate();
    }

Localization changes are bound to OS language

In some recently-released phones, users cannot change the language inside the app which is using lingver, the language is not independent of the OS language.

This happens in samsung A10, api 29 and xiaomi redmi k20 pro api 29
But It works fine in Samsung j7Pro api 28

Maybe it's an issue in api level?

Works on local, but not in Google Play

Hi,
I've testing the library to change language programatically and it works perfectly. The problem is when I put the app on Google Play. The same app doesn't work, doesn't change the language.

I've tried 2 times, it's exactly the same app on local and Google Play.

Anyone with same issue?

Thanks a lot!

Layout Direction bug after split-screen mode

I've set the locale with this code:
Lingver.getInstance().setLocale(requireContext(), "fa")
It use RTL layout direction. Everything works great, but when I use the app in split screen mode and then maximize it again layout direction resets to LTR (but it uses farsi strings).

How can I fix the issue?

How to get default system locale?

I don't know if this is a problem with me using this library in Java project, or am I missing something? I just want to get default system locale (the phone's locale).


Lingver.getInstance().systemLocale.getLanguage();

error: systemLocale has private access in Lingver


I also tried:

Lingver.defaultLocale.getLanguage();

error: defaultLocale has private access in Lingver


Then there is getSystemLocale$com_yariksoffice_lingver_library():

image

Usage of Kotlin internal declaration from different module

ANR when calling Lingver.init in Application.onCreate

We're seeing a lot of ANRs being reported that are caused by Lingver init call. This is occurring during the process creation time (cold start), when calling Lingver.init(context) on the Application.onCreate

Unable to repro this. Is there any resolution to this?


Lingver SDK version: 1.3.0

Stats:
100% of them are background ANRs

OS:

  • 50% in Android 11
  • 50% in Android 12

Devices:

  • 76% in Samsung
  • 9% in Vivo
  • 6% in Xiaomi
  • 9% others

main (waiting)
tid=1 systid=27706
Triggered ANR
Root blocking
IO Root blocking

Stack trace
java.lang.Object.wait (Object.java)
java.lang.Object.wait (Object.java:442)
java.lang.Object.wait (Object.java:568)
android.app.SharedPreferencesImpl.awaitLoadedLocked (SharedPreferencesImpl.java:279)
android.app.SharedPreferencesImpl.getBoolean (SharedPreferencesImpl.java:344)
com.yariksoffice.lingver.store.PreferenceLocaleStore.isFollowingSystemLocale (PreferenceLocaleStore.kt:69)
com.yariksoffice.lingver.Lingver.initialize$com_yariksoffice_lingver_library (Lingver.kt:120)
com.yariksoffice.lingver.Lingver$Companion.init (Lingver.kt:192)
com.yariksoffice.lingver.Lingver$Companion.init (Lingver.kt:182)
com.yariksoffice.lingver.Lingver$Companion.init$default (Lingver.kt:181)
com.myapp.main.MyApplication.onCreate (MyApplication.java:80)
android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1211)
android.app.ActivityThread.handleBindApplication (ActivityThread.java:7506)
android.app.ActivityThread.access$1600 (ActivityThread.java:310)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2281)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8663)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:567)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1135) 

Part of the UI is not loading the correct language

I have a BaseActivity which Extends AppCompatActivity.

public class BaseActivity extends AppCompatActivity {

    private final String TAG = "BaseActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Log.e(TAG, "LANGUAGE : " + C.CurrentLanguage);
    }


    @Override
    public void applyOverrideConfiguration(Configuration overrideConfiguration) {
        if (overrideConfiguration != null) {
            int uiMode = overrideConfiguration.uiMode;
            overrideConfiguration.setTo(getBaseContext().getResources().getConfiguration());
            overrideConfiguration.uiMode = uiMode;
        }
        super.applyOverrideConfiguration(overrideConfiguration);
    }
}

After Changing the Language it look like this.

71251609-d405f880-2348-11ea-8c0f-c02ea3c09d1e

I have checked for missing translations. But all the strings are there . But not loading some of the strings. How to solve this issue

Not possible to change "Cyrillic" to "Latin".

Hello,

I have Serbian language in the app. It can be "Latin" or "Cyrillic".
It's not possible to change this using this library.

For example to change letters to "Latin", you have to do this:
Lingver.getInstance().setLocale(context, new Locale.Builder().setLanguage("sr").setScript("Latn").build());

But it's not working as expected.
In this case this code is resetting the app language to default system language, English in my case.

This one is working fine when ".setScript("Latn")" is not being used:
Lingver.getInstance().setLocale(context, new Locale.Builder().setLanguage("sr").build());

Could you fix this bug please?

inconsistent language between ui components

Screenshot_20200527-102150
Screenshot_20200527-102244
components of the app that use strings directly in xml eg the layouts correctly respond to language changes, however, Strings pulled by getString(R.string.xxx) remain to the system locale language

Why "followSystemLocale" is not true by default?

I was quite surprised when I realized that isFollowingSystemLocale is false by default. Let me explain my use case, maybe I'm missing something. I want my app locale to match system locale, unless the user specified otherwise explicitly in the app settings. So if the user just launches the app, then changes the system locale, I want the app to automatically change the locale to the system one. If the user then changes the app locale to a different one in settings, I want that locale to stick, so now system locale doesn't matter anymore.
If isFollowingSystemLocale was 'true' by default, everything would work naturally. I would use Lingver.setLocale() only when the user changes the locale in app settings. But since isFollowingSystemLocale is false by default, the first call to Lingver.init() on the first app run persists the locale, and subsequent system locale changes don't have any effect. So to achieve what I want, I need to call setFollowSystemLocale(true), but only on the first app run. Which is doable, but a bit annoying.

At the same time I realize that you probably can't change the default value now, because all apps with Lingver that didn't change followSystemLocale explicitly would start behaving differently.

And thank you for creating the library and publishing that blog post!

Could not find com.github.YarikSOffice:lingver:1.3.0

i add
maven { url 'https://jitpack.io' }

implementation "com.github.YarikSOffice:lingver:1.3.0"

but

Execution failed for task ':app:dataBindingMergeDependencyArtifactsDebug'.
> Could not resolve all files for configuration ':app:debugCompileClasspath'.
   > Could not find com.github.YarikSOffice:lingver:1.3.0.
     Required by:
         project :app

Possible solution:
 - Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html

Locale change not working in release build with dexguard

Library is working fine in debug build but after making the release build with dexguard library does not work.
I also keep the package in dexguard rules.
-keep class com.yariksoffice.lingver.** { *; }
But still not working

It does not work for all languages

I have notice that this library does not change the locale for all languages, for example Tagalog (iso code tl or tl-rPH in Android Studio) doesn't work.

Attached an example project to demonstrate the issue.
LocaleTest.zip

Doesn't work with Robolectric unit tests

You'd get the following error if you use Robolectric for unit testing. The current workaround is to catch IllegalStateException.

java.lang.IllegalStateException: Already initialized
at com.yariksoffice.lingver.Lingver$Companion.init(Lingver.kt:192)
at com.yariksoffice.lingver.Lingver$Companion.init(Lingver.kt:182)
at com.yariksoffice.lingver.Lingver.init(Lingver.kt)

This happens because Robolectric calls Application#onCreate() on each test.

Incorrect language, when device set two or more locales

Steps to reproduce:

  1. Have Android 9 (maybe 10 too)
  2. Add languages in device. F.e. English and Russian
  3. Switch device to Russian
  4. Switch application to English.
  5. Observe

Expected result:

  1. App language is English
  2. Actual result: app language is Russian (maybe partially)

Notes:
I think problem still is in "setLocaleForApi24".

EDIT 1:
further investigation lead me, that problem appears if I use language like "en_US", not just "en".

EDIT 2:
This case:
изображение

Note that you need to update all already fetched locale-based data manually.

I am seeing some unexpected behavior even after calling
Lingver.getInstance().setLocale(this, language)
properly. The new language locale strings won`t show up unless app is exited and started again.
I guess it is related to the point mention in notes "Note that you need to update all already fetched locale-based data manually. Lingver is not responsible for that."
What exactly means by updating already fetched data manually and how to do it? What will be the best-practice for this ?

Publish to JCenter or Maven Central

I'm investigating using Lingver from my project, but that would require it to be published somewhere other than jitpack. Would you be able to publish to either JCenter or Maven Central?

AAB release build not working for notification translation

When app in release mode, aab file do not support arabic translation.
In app gradle I already have -
bundle { language { enableSplit = false } }
In proguard file, I have
-keep class com.yariksoffice.lingver.** { *; }

I am calling below method on Message Recieved(Push notification is received)
Lingver.getInstance().setLocale(this, Lingver.getInstance().getLanguage());

please suggest @YarikSOffice

Build error when adding lingver dependency

I get this build error when I add the dependency:
More than one file was found with OS independent path 'META-INF/library_release.kotlin_module'

I'm using Android Studio 3.5.2 with Kotlin 1.3.50.

Not working after publication?

Firstly, thank you for the library.

While I debug on my computer everything is working fine, when I publish to Play Store, and I download from there, then, if the default language of the device is English, the library is not working. If the default language is Russian, everything is working fine.

Could you help to solve the issue?

Fragment's menu not localized on rotation

Steps to reproduce:

  • Create fragment
  • Add menu to fragment
  • Rotate device

If you add something like this:
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
menu.clear()
MenuInflater(activity?.applicationContext).let {
it.inflate(R.menu.main_menu, menu)
super.onPrepareOptionsMenu(menu)
}
}

it solves problem, but adds new one - app:showAsAction="always" is ignored

I've created fork to test this out and maybe add some fixes if have any, but no luck.
If you want sample, please check https://github.com/RumataEstorish/lingver/tree/fragment_menu_test

When choosing Arabic language RTL isn't working properly

Hi! When I'm changing the app language to Arabic (from English) the app is struggling with re-drawing the layout to an RTL, even after calling activity.recreate(). It does well only when I close and open the app again. Same things happening when switching RTL -> LTR. Could you please give any suggestion, how could it be fixed? Thank you.

Does not works for Arabic

Both English (en) and Persian (fa) switching works properly but when I try to set language to Arabic, app displays default language strings and maked LTR, also when I get language value, it returns ar!

Sorry for my bad English :)

How to change locale without restarting A activity?

I have:

  • activity A with option "Change Language", activity B opens after click on "Change Language"
  • activity B with list of languages, language is changed after click on element of list by:
 val localeCode = languageList[index]
 Lingver.getInstance().setLocale(activity.application, localeCode)
 activity.finish()/*finish activity B*/

[result]: Activity A resumed, but locale was not changed

The same behaviour is implemented at Telegram app

[Question] Why not use AppCompat's setApplicationLocales and getApplicationLocales?

Hello,

Thank you for the library and the blog post. It has been very useful to me.
This is more of a question more suitable in a discussion tab but I couldnt find a discussion tab so adding it here.

I have a question that I am curious about.
While checking android docs about handling in app language changes, they mentioned using androidx AppCompat's setApplicationLocales and getApplicationLocales which seems to have a consistent api accross different api levels, and also auto persists language changes using the autoStoreLocales.

I am wondering why the library does not utilize that and instead handle different api levels differently and manages its own storage.

Are there downsides to the appcompat approach and you think the manual way offers something better or do you think the appcompat's way is actually better but did not update the code cause why fix what is already working or you don't have the time for it.

Thank you very much and if anything I said doesnt seem right, please bear in mind I am a beginner android dev

Stops working in production app

The library works fine when I install it directly from Android Studio.

However, when I create signed app bundle, upload it to play store and download it from there it stops working. Language is always in system's locale. I'm not using proguard which should change the source code.
I own devices with API 29, 23, 21 and only 21 works correctly on play store's version.
Any idea how to fix this strange behavior?

res.updateConfiguration() deprecated in API 25

Hello,

I was reviewing the code of the library and I noticed that it's using res.updateConfiguration() (deprecated in API 25) for all API versions, instead of using the approach described in the article.

@Suppress("DEPRECATION")
private fun updateResources(context: Context, locale: Locale) {
Locale.setDefault(locale)
val res = context.resources
val current = res.configuration.getLocaleCompat()
if (current == locale) return
val config = Configuration(res.configuration)
when {
isAtLeastSdkVersion(VERSION_CODES.N) -> setLocaleForApi24(config, locale)
isAtLeastSdkVersion(VERSION_CODES.JELLY_BEAN_MR1) -> config.setLocale(locale)
else -> config.locale = locale
}
res.updateConfiguration(config, res.displayMetrics)
}

Update already fetched locale-based data in activities and fragments that reside in the backstack after changing locale.

This is not an issue with lingver but more like the followup that I've never figured out.
In light of

Note that you need to update all already fetched locale-based data manually. Lingver is not responsible for that.

I understand that Lingver's responsibility ends after updating the locale using
Lingver.getInstance().setLocale(this, language)

what I have is a button in a custom ActionBar, pressing that button calls the Lingver.getInstance().setLocale(this, language) and the ActionBar is used on every activity on the project, so that on any activity the user is able to change the language at any time by pressing that button.

the main issue is when there are activities and/or fragments that are already open in the backstack.

so what's the go-to approach? how can one change the data (e.g. TextView, RecyclerView, etc...) that are already fetched in activities and fragments that are on the backstack?

I've tried to override onConfigurationChanged inside my activity class and reset my views there
but it was never called even after adding android:configChanges="locale|layoutDirection" to the activity in the android manifest

I have also tried to call recreate() after using Lingver.getInstance().setLocale(this, language)
it does work as it resets the activity but it gave me literal hell for my viewpager and fragments configuration so I'm looking for potentially better alternatives.

System-Default Language-Key?

Hi,

first of all thanks for your Lingver library project.

Is there a way or a "special language-key" that always returns the

defaultLocale: Locale = Locale.getDefault()

from the app-start?

Thanks and Regards

Fonts are not loading on setLocale().

This is a great lib for localization. I saw a small point: there was no res/font folder in the sample project and this means the fonts that developers set separately for each locale are not be loaded on recreating the activity, they will only be loaded and set on starting the app again. So by changing the language on a hypothetical SettingsActivity and doing a recreate(), the specific fonts for new locale will not be loaded.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.