Merge pull request #3241 from deltachat/r10s/use-system-language

use system language, support per-app-language-selection
This commit is contained in:
Asiel Díaz Benítez 2024-08-25 15:26:51 +02:00 committed by GitHub
commit c4698fcf60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 136 additions and 480 deletions

View file

@ -132,6 +132,11 @@ android {
jniLibs.srcDirs = ['libs']
}
}
androidResources {
generateLocaleConfig true
}
lint {
abortOnError false
}

View file

@ -19,7 +19,6 @@ cp $RES/values/strings.xml $RES/values-$LANG/strings.xml
touch -t 201901010000 $RES/values-$LANG/strings.xml
echo "$RES/values-$LANG/strings.xml added:"
echo "- add the name to $RES/values/arrays.xml"
echo "- if needed, language mappings can be added to .tx/config"
echo "- pull translations using ./scripts/tx-pull-translations.sh"
echo " (on problems, 'tx -d pull' gives verbose output)"

View file

@ -44,14 +44,13 @@ import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.notifications.InChatSounds;
import org.thoughtcrime.securesms.notifications.NotificationCenter;
import org.thoughtcrime.securesms.util.AndroidSignalProtocolLogger;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.SignalProtocolLoggerProvider;
import org.thoughtcrime.securesms.util.Util;
import java.io.File;
import java.util.concurrent.TimeUnit;
//import com.squareup.leakcanary.LeakCanary;
public class ApplicationContext extends MultiDexApplication {
private static final String TAG = ApplicationContext.class.getSimpleName();
@ -191,19 +190,13 @@ public class ApplicationContext extends MultiDexApplication {
InChatSounds.getInstance(this);
dcLocationManager = new DcLocationManager(this);
try {
DynamicLanguage.setContextLocale(this, DynamicLanguage.getSelectedLocale(this));
}
catch (Exception e) {
e.printStackTrace();
}
DynamicTheme.setDefaultDayNightMode(this);
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Util.localeChanged();
DcHelper.setStockTranslations(context);
}
}, filter);

View file

@ -117,8 +117,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
if (key.equals(Prefs.THEME_PREF)) {
DynamicTheme.setDefaultDayNightMode(this);
recreate();
} else if (key.equals(Prefs.LANGUAGE_PREF)) {
finish();
}
}

View file

@ -15,24 +15,19 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import java.lang.reflect.Field;
import java.util.Locale;
public abstract class BaseActionBarActivity extends AppCompatActivity {
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
public static final String LOCALE_EXTRA = "locale_extra";
protected final DynamicLanguage dynamicLanguage = new DynamicLanguage();
protected DynamicTheme dynamicTheme = new DynamicTheme();
protected void onPreCreate() {
dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this);
}
@Override
@ -49,14 +44,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
super.onResume();
initializeScreenshotSecurity();
dynamicTheme.onResume(this);
dynamicLanguage.onResume(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// on orientation changes locale is reset in the context/activity so set locale as onCreate()
dynamicLanguage.onCreate(this);
}
@Override
@ -121,18 +108,9 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
protected <T extends Fragment> T initFragment(@IdRes int target,
@NonNull T fragment,
@Nullable Locale locale)
{
return initFragment(target, fragment, locale, null);
}
protected <T extends Fragment> T initFragment(@IdRes int target,
@NonNull T fragment,
@Nullable Locale locale,
@Nullable Bundle extras)
{
Bundle args = new Bundle();
args.putSerializable(LOCALE_EXTRA, locale);
if (extras != null) {
args.putAll(extras);

View file

@ -41,7 +41,6 @@ import org.thoughtcrime.securesms.util.views.ProgressDialog;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public abstract class BaseConversationListFragment extends Fragment implements ActionMode.Callback {
@ -92,11 +91,11 @@ public abstract class BaseConversationListFragment extends Fragment implements A
ArrayList<Uri> uris = getSharedUris(getActivity());
String message;
if (isForwarding(getActivity())) {
message = String.format(Locale.getDefault(), getString(R.string.ask_forward_multiple), selectedChats.size());
message = String.format(Util.getLocale(), getString(R.string.ask_forward_multiple), selectedChats.size());
} else if (!uris.isEmpty()) {
message = String.format(Locale.getDefault(), getString(R.string.share_multiple_attachments_multiple_chats), uris.size(), selectedChats.size());
message = String.format(Util.getLocale(), getString(R.string.share_multiple_attachments_multiple_chats), uris.size(), selectedChats.size());
} else {
message = String.format(Locale.getDefault(), getString(R.string.share_text_multiple_chats), selectedChats.size(), getSharedText(getActivity()));
message = String.format(Util.getLocale(), getString(R.string.share_text_multiple_chats), selectedChats.size(), getSharedText(getActivity()));
}
Context context = getContext();
if (context != null) {

View file

@ -9,14 +9,12 @@ import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.Locale;
import java.util.Set;
public interface BindableConversationItem extends Unbindable {
void bind(@NonNull DcMsg messageRecord,
@NonNull DcChat dcChat,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<DcMsg> batchSelected,
@NonNull Recipient recipients,
boolean pulseHighlight);

View file

@ -7,7 +7,6 @@ import com.b44t.messenger.DcLot;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import java.util.Locale;
import java.util.Set;
public interface BindableConversationListItem extends Unbindable {
@ -15,6 +14,6 @@ public interface BindableConversationListItem extends Unbindable {
public void bind(@NonNull ThreadRecord thread,
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests, @NonNull Locale locale,
@NonNull GlideRequests glideRequests,
@NonNull Set<Long> selectedThreads, boolean batchMode);
}

View file

@ -32,7 +32,7 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
public void onCreate(Bundle bundle, boolean ready) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.pref_blocked_contacts);
initFragment(android.R.id.content, new BlockedAndShareContactsFragment(), null, getIntent().getExtras());
initFragment(android.R.id.content, new BlockedAndShareContactsFragment(), getIntent().getExtras());
}
@Override

View file

@ -210,7 +210,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
getWindow().getDecorView().setBackgroundColor(color);
fragment = initFragment(R.id.fragment_content, new ConversationFragment(), dynamicLanguage.getCurrentLocale());
fragment = initFragment(R.id.fragment_content, new ConversationFragment());
initializeActionBar();
initializeViews();

View file

@ -46,7 +46,6 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@ -66,7 +65,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
{
private static final int MAX_CACHE_SIZE = 40;
private static final String TAG = ConversationAdapter.class.getSimpleName();
private final Map<Integer,SoftReference<DcMsg>> recordCache =
Collections.synchronizedMap(new LRUCache<Integer,SoftReference<DcMsg>>(MAX_CACHE_SIZE));
@ -87,7 +85,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
private final @Nullable ItemClickListener clickListener;
private final @NonNull GlideRequests glideRequests;
private final @NonNull Locale locale;
private final @NonNull Recipient recipient;
private final @NonNull LayoutInflater inflater;
private final @NonNull Context context;
@ -213,12 +210,10 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
public ConversationAdapter(@NonNull Context context,
@NonNull DcChat dcChat,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable ItemClickListener clickListener,
@NonNull Recipient recipient) {
this.dcChat = dcChat;
this.glideRequests = glideRequests;
this.locale = locale;
this.clickListener = clickListener;
this.recipient = recipient;
this.context = context;
@ -243,7 +238,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
long elapsed = now - pulseHighlightingSince;
boolean pulseHighlight = (positionCurrentlyPulseHighlighting == position && elapsed < PULSE_HIGHLIGHT_MILLIS);
holder.getItem().bind(getMsg(position), dcChat, glideRequests, locale, batchSelected, recipient, pulseHighlight);
holder.getItem().bind(getMsg(position), dcChat, glideRequests, batchSelected, recipient, pulseHighlight);
}
@Override
@ -374,7 +369,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
*/
@Override
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
viewHolder.setText(DateUtils.getRelativeDate(getContext(), locale, getSortTimestamp(position)));
viewHolder.setText(DateUtils.getRelativeDate(getContext(), getSortTimestamp(position)));
}

View file

@ -76,7 +76,6 @@ import org.thoughtcrime.securesms.videochat.VideochatUtil;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
@ -85,7 +84,6 @@ import java.util.TimerTask;
public class ConversationFragment extends MessageSelectorFragment
{
private static final String TAG = ConversationFragment.class.getSimpleName();
private static final String KEY_LIMIT = "limit";
private static final int SCROLL_ANIMATION_THRESHOLD = 50;
private static final int CODE_ADD_EDIT_CONTACT = 77;
@ -99,7 +97,6 @@ public class ConversationFragment extends MessageSelectorFragment
private long chatId;
private int startingPosition;
private boolean firstLoad;
private Locale locale;
private RecyclerView list;
private RecyclerView.ItemDecoration lastSeenDecoration;
private StickyHeaderDecoration dateDecoration;
@ -115,7 +112,6 @@ public class ConversationFragment extends MessageSelectorFragment
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
this.locale = (Locale) getArguments().getSerializable(PassphraseRequiredActionBarActivity.LOCALE_EXTRA);
this.dcContext = DcHelper.getContext(getContext());
DcEventCenter eventCenter = DcHelper.getEventCenter(getContext());
@ -285,7 +281,7 @@ public class ConversationFragment extends MessageSelectorFragment
private void initializeListAdapter() {
if (this.recipient != null && this.chatId != -1) {
ConversationAdapter adapter = new ConversationAdapter(getActivity(), this.recipient.getChat(), GlideApp.with(this), locale, selectionClickListener, this.recipient);
ConversationAdapter adapter = new ConversationAdapter(getActivity(), this.recipient.getChat(), GlideApp.with(this), selectionClickListener, this.recipient);
list.setAdapter(adapter);
if (dateDecoration != null) {

View file

@ -77,7 +77,6 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
@ -97,7 +96,6 @@ public class ConversationItem extends BaseConversationItem
private static final int MAX_MEASURE_CALLS = 3;
private DcContact dcContact;
private Locale locale;
// Whether the sender's avatar and name should be shown (usually the case in group threads):
private boolean showSender;
private GlideRequests glideRequests;
@ -172,13 +170,11 @@ public class ConversationItem extends BaseConversationItem
public void bind(@NonNull DcMsg messageRecord,
@NonNull DcChat dcChat,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<DcMsg> batchSelected,
@NonNull Recipient recipients,
boolean pulseHighlight)
{
bind(messageRecord, dcChat, batchSelected, pulseHighlight, recipients);
this.locale = locale;
this.glideRequests = glideRequests;
this.showSender = (dcChat.isMultiUser() && !messageRecord.isOutgoing()) || messageRecord.getOverrideSenderName() != null;
@ -196,7 +192,7 @@ public class ConversationItem extends BaseConversationItem
setAuthor(messageRecord, showSender);
setMessageSpacing(context);
setReactions(messageRecord);
setFooter(messageRecord, locale);
setFooter(messageRecord);
setQuote(messageRecord);
if (Util.isTouchExplorationEnabled(context)) {
setContentDescription();
@ -748,7 +744,7 @@ public class ConversationItem extends BaseConversationItem
}
}
private void setFooter(@NonNull DcMsg current, @NonNull Locale locale) {
private void setFooter(@NonNull DcMsg current) {
ViewUtil.updateLayoutParams(footer, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
footer.setVisibility(GONE);
@ -756,7 +752,7 @@ public class ConversationItem extends BaseConversationItem
ConversationItemFooter activeFooter = getActiveFooter(current);
activeFooter.setVisibility(VISIBLE);
activeFooter.setMessageRecord(current, locale);
activeFooter.setMessageRecord(current);
}
private void setReactions(@NonNull DcMsg current) {

View file

@ -175,7 +175,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
fragmentContainer = findViewById(R.id.fragment_container);
Bundle bundle = new Bundle();
conversationListFragment = initFragment(R.id.fragment_container, new ConversationListFragment(), dynamicLanguage.getCurrentLocale(), bundle);
conversationListFragment = initFragment(R.id.fragment_container, new ConversationListFragment(), bundle);
initializeSearchListener();
@ -384,7 +384,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
if (trimmed.length() > 0) {
if (searchFragment == null) {
searchFragment = SearchFragment.newInstance(dynamicLanguage.getCurrentLocale());
searchFragment = SearchFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, searchFragment, null)
.commit();

View file

@ -35,7 +35,6 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.lang.ref.WeakReference;
import java.util.Locale;
/**
* A CursorAdapter for building a list of conversation threads.
@ -52,7 +51,6 @@ class ConversationListAdapter extends BaseConversationListAdapter<ConversationLi
private @NonNull DcContext dcContext;
private @NonNull DcChatlist dcChatlist;
private final @NonNull GlideRequests glideRequests;
private final @NonNull Locale locale;
private final @NonNull LayoutInflater inflater;
private final @Nullable ItemClickListener clickListener;
@ -79,7 +77,6 @@ class ConversationListAdapter extends BaseConversationListAdapter<ConversationLi
ConversationListAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable ItemClickListener clickListener)
{
super();
@ -87,7 +84,6 @@ class ConversationListAdapter extends BaseConversationListAdapter<ConversationLi
this.glideRequests = glideRequests;
this.dcContext = DcHelper.getContext(context);
this.dcChatlist = new DcChatlist(0, 0);
this.locale = locale;
this.inflater = LayoutInflater.from(context);
this.clickListener = clickListener;
setHasStableIds(true);
@ -134,7 +130,7 @@ class ConversationListAdapter extends BaseConversationListAdapter<ConversationLi
DcChat chat = dcContext.getChat(dcChatlist.getChatId(i));
DcLot summary = dcChatlist.getSummary(i, chat);
viewHolder.getItem().bind(DcHelper.getThreadRecord(context, summary, chat), dcChatlist.getMsgId(i), summary, glideRequests, locale, batchSet, batchMode);
viewHolder.getItem().bind(DcHelper.getThreadRecord(context, summary, chat), dcChatlist.getMsgId(i), summary, glideRequests, batchSet, batchMode);
}
@Override

View file

@ -19,8 +19,6 @@ import static org.thoughtcrime.securesms.util.RelayUtil.isSharing;
public class ConversationListArchiveActivity extends PassphraseRequiredActionBarActivity
implements ConversationListFragment.ConversationSelectedListener
{
private ConversationListFragment conversationListFragment;
@Override
protected void onCreate(Bundle icicle, boolean ready) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -33,8 +31,7 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
Bundle bundle = new Bundle();
bundle.putBoolean(ConversationListFragment.ARCHIVE, true);
conversationListFragment = initFragment(android.R.id.content, new ConversationListFragment(), dynamicLanguage.getCurrentLocale(), bundle);
initFragment(android.R.id.content, new ConversationListFragment(), bundle);
}
@Override

View file

@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
@ -67,7 +66,6 @@ public class ConversationListFragment extends BaseConversationListFragment
private RecyclerView list;
private View emptyState;
private TextView emptySearch;
private Locale locale;
private final String queryFilter = "";
private boolean archive;
private Timer reloadTimer;
@ -77,7 +75,6 @@ public class ConversationListFragment extends BaseConversationListFragment
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
locale = (Locale) getArguments().getSerializable(PassphraseRequiredActionBarActivity.LOCALE_EXTRA);
archive = getArguments().getBoolean(ARCHIVE, false);
DcEventCenter eventCenter = DcHelper.getEventCenter(requireActivity());
@ -131,7 +128,7 @@ public class ConversationListFragment extends BaseConversationListFragment
setHasOptionsMenu(true);
initializeFabClickListener(false);
list.setAdapter(new ConversationListAdapter(requireActivity(), GlideApp.with(this), locale, this));
list.setAdapter(new ConversationListAdapter(requireActivity(), GlideApp.with(this), this));
loadChatlistAsync();
chatlistJustLoaded = true;
}

View file

@ -51,11 +51,11 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public class ConversationListItem extends RelativeLayout
@ -108,18 +108,16 @@ public class ConversationListItem extends RelativeLayout
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> selectedThreads,
boolean batchMode)
{
bind(thread, msgId, dcSummary, glideRequests, locale, selectedThreads, batchMode, null);
bind(thread, msgId, dcSummary, glideRequests, selectedThreads, batchMode, null);
}
public void bind(@NonNull ThreadRecord thread,
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> selectedThreads,
boolean batchMode,
@Nullable String highlightSubstring)
@ -135,7 +133,7 @@ public class ConversationListItem extends RelativeLayout
int unreadCount = thread.getUnreadCount();
if (highlightSubstring != null) {
this.fromView.setText(getHighlightedSpan(locale, recipient.getName(), highlightSubstring));
this.fromView.setText(getHighlightedSpan(recipient.getName(), highlightSubstring));
} else {
this.fromView.setText(recipient, state!=DcMsg.DC_STATE_IN_FRESH);
}
@ -146,7 +144,7 @@ public class ConversationListItem extends RelativeLayout
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_subject_color));
if (thread.getDate() > 0) {
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), thread.getDate());
dateView.setText(date);
}
else {
@ -176,16 +174,15 @@ public class ConversationListItem extends RelativeLayout
public void bind(@NonNull DcContact contact,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable String highlightSubstring)
{
this.selectedThreads = Collections.emptySet();
Recipient recipient = new Recipient(getContext(), contact);
this.glideRequests = glideRequests;
fromView.setText(getHighlightedSpan(locale, contact.getDisplayName(), highlightSubstring));
fromView.setText(getHighlightedSpan(contact.getDisplayName(), highlightSubstring));
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
subjectView.setText(getHighlightedSpan(locale, contact.getAddr(), highlightSubstring));
subjectView.setText(getHighlightedSpan(contact.getAddr(), highlightSubstring));
dateView.setText("");
dateView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
archivedBadgeView.setVisibility(GONE);
@ -200,7 +197,6 @@ public class ConversationListItem extends RelativeLayout
public void bind(@NonNull DcMsg messageResult,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable String highlightSubstring)
{
DcContext dcContext = DcHelper.getContext(getContext());
@ -211,11 +207,11 @@ public class ConversationListItem extends RelativeLayout
fromView.setText(recipient, true);
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
subjectView.setText(getHighlightedSpan(locale, messageResult.getSummarytext(512), highlightSubstring));
subjectView.setText(getHighlightedSpan(messageResult.getSummarytext(512), highlightSubstring));
long timestamp = messageResult.getTimestamp();
if(timestamp>0) {
dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getTimestamp()));
dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), messageResult.getTimestamp()));
}
else {
dateView.setText("");
@ -311,8 +307,7 @@ public class ConversationListItem extends RelativeLayout
ta.recycle();
}
private Spanned getHighlightedSpan(@NonNull Locale locale,
@Nullable String value,
private Spanned getHighlightedSpan(@Nullable String value,
@Nullable String highlight)
{
if (TextUtils.isEmpty(value)) {
@ -325,8 +320,8 @@ public class ConversationListItem extends RelativeLayout
return new SpannableString(value);
}
String normalizedValue = value.toLowerCase(locale);
String normalizedTest = highlight.toLowerCase(locale);
String normalizedValue = value.toLowerCase(Util.getLocale());
String normalizedTest = highlight.toLowerCase(Util.getLocale());
List<String> testTokens = Stream.of(normalizedTest.split(" ")).filter(s -> s.trim().length() > 0).toList();
Spannable spanned = new SpannableString(value);

View file

@ -14,7 +14,6 @@ import com.b44t.messenger.DcLot;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import java.util.Locale;
import java.util.Set;
public class ConversationListItemInboxZero extends LinearLayout implements BindableConversationListItem{
@ -41,7 +40,7 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
}
@Override
public void bind(@NonNull ThreadRecord thread, int msgId, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode) {
public void bind(@NonNull ThreadRecord thread, int msgId, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Set<Long> selectedThreads, boolean batchMode) {
}
}

View file

@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.JsonUtils;
import java.io.ByteArrayInputStream;
import java.util.Locale;
import java.util.Set;
public class ConversationUpdateItem extends BaseConversationItem
@ -62,7 +61,6 @@ public class ConversationUpdateItem extends BaseConversationItem
public void bind(@NonNull DcMsg messageRecord,
@NonNull DcChat dcChat,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<DcMsg> batchSelected,
@NonNull Recipient conversationRecipient,
boolean pulseUpdate)

View file

@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Locale;
import java.util.Set;
public class ConversationVideochatItem extends LinearLayout
@ -57,7 +56,6 @@ public class ConversationVideochatItem extends LinearLayout
public void bind(@NonNull DcMsg dcMsg,
@NonNull DcChat dcChat,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<DcMsg> batchSelected,
@NonNull Recipient conversationRecipient,
boolean pulseUpdate)
@ -76,14 +74,14 @@ public class ConversationVideochatItem extends LinearLayout
contactPhoto.setAvatar(glideRequests, new Recipient(getContext(), dcContact), true);
setSelected(batchSelected.contains(dcMsg));
setFooter(dcMsg, locale);
setFooter(dcMsg);
}
private void setFooter(@NonNull DcMsg dcMsg, @NonNull Locale locale) {
private void setFooter(@NonNull DcMsg dcMsg) {
ViewUtil.updateLayoutParams(footer, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
footer.setVisibility(VISIBLE);
footer.setMessageRecord(dcMsg, locale);
footer.setMessageRecord(dcMsg);
}
@Override

View file

@ -5,6 +5,8 @@ import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import org.thoughtcrime.securesms.util.Util;
import java.io.InputStream;
import java.util.Locale;
@ -25,7 +27,7 @@ public class LocalHelpActivity extends WebViewActivity
String helpPath = "help/LANG/help.html";
String helpLang = "en";
try {
Locale locale = dynamicLanguage.getCurrentLocale();
Locale locale = Util.getLocale();
String appLang = locale.getLanguage();
String appCountry = locale.getCountry();
if (assetExists(helpPath.replace("LANG", appLang))) {

View file

@ -30,7 +30,7 @@ public class LogViewActivity extends BaseActionBarActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.log_view_activity);
logViewFragment = new LogViewFragment(dynamicLanguage);
logViewFragment = new LogViewFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, logViewFragment);
transaction.commit();

View file

@ -41,8 +41,8 @@ import com.b44t.messenger.DcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -56,13 +56,9 @@ import java.util.Date;
import java.util.Locale;
public class LogViewFragment extends Fragment {
private static final String TAG = LogViewFragment.class.getSimpleName();
private EditText logPreview;
private final @NonNull DynamicLanguage dynamicLanguage;
public LogViewFragment(DynamicLanguage dynamicLanguage) {
this.dynamicLanguage = dynamicLanguage;
public LogViewFragment() {
}
@Override
@ -252,10 +248,10 @@ public class LogViewFragment extends Fragment {
builder.append("reliableService=").append(
Prefs.reliableService(context)).append("\n");
Locale locale = fragment.dynamicLanguage.getCurrentLocale();
Locale locale = Util.getLocale();
builder.append("lang=").append(locale.toString()).append("\n");
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
boolean isRtl = DynamicLanguage.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
builder.append("rtl=").append(isRtl).append("\n");
}

View file

@ -156,7 +156,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
CharSequence relativeTimeSpan;
if (mediaItem.date > 0) {
relativeTimeSpan = DateUtils.getExtendedRelativeTimeSpanString(this,dynamicLanguage.getCurrentLocale(), mediaItem.date);
relativeTimeSpan = DateUtils.getExtendedRelativeTimeSpanString(this, mediaItem.date);
} else {
relativeTimeSpan = getString(R.string.draft);
}

View file

@ -326,33 +326,28 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
fragment = new ProfileSettingsFragment();
args.putInt(ProfileSettingsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId);
args.putInt(ProfileSettingsFragment.CONTACT_ID_EXTRA, (contactId==0&&!isGlobalProfile())? -1 : contactId);
args.putSerializable(ProfileSettingsFragment.LOCALE_EXTRA, dynamicLanguage.getCurrentLocale());
break;
case TAB_GALLERY:
fragment = new ProfileGalleryFragment();
args.putInt(ProfileGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId);
args.putSerializable(ProfileGalleryFragment.LOCALE_EXTRA, dynamicLanguage.getCurrentLocale());
break;
case TAB_AUDIO:
fragment = new ProfileDocumentsFragment();
args.putInt(ProfileDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId);
args.putBoolean(ProfileDocumentsFragment.SHOW_AUDIO_EXTRA, true);
args.putSerializable(ProfileDocumentsFragment.LOCALE_EXTRA, dynamicLanguage.getCurrentLocale());
break;
case TAB_WEBXDC:
fragment = new ProfileDocumentsFragment();
args.putInt(ProfileDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId);
args.putBoolean(ProfileDocumentsFragment.SHOW_WEBXDC_EXTRA, true);
args.putSerializable(ProfileDocumentsFragment.LOCALE_EXTRA, dynamicLanguage.getCurrentLocale());
break;
default:
fragment = new ProfileDocumentsFragment();
args.putInt(ProfileGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId);
args.putSerializable(ProfileDocumentsFragment.LOCALE_EXTRA, dynamicLanguage.getCurrentLocale());
break;
}

View file

@ -22,13 +22,11 @@ import org.thoughtcrime.securesms.util.MediaUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
class ProfileDocumentsAdapter extends StickyHeaderGridAdapter {
private final Context context;
private final Locale locale;
private final ItemClickListener itemClickListener;
private final Set<DcMsg> selected;
@ -60,11 +58,9 @@ class ProfileDocumentsAdapter extends StickyHeaderGridAdapter {
ProfileDocumentsAdapter(@NonNull Context context,
BucketedThreadMedia media,
Locale locale,
ItemClickListener clickListener)
{
this.context = context;
this.locale = locale;
this.media = media;
this.itemClickListener = clickListener;
this.selected = new HashSet<>();
@ -86,7 +82,7 @@ class ProfileDocumentsAdapter extends StickyHeaderGridAdapter {
@Override
public void onBindHeaderViewHolder(StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
((HeaderHolder)viewHolder).textView.setText(media.getName(section, locale));
((HeaderHolder)viewHolder).textView.setText(media.getName(section));
}
@Override
@ -135,7 +131,7 @@ class ProfileDocumentsAdapter extends StickyHeaderGridAdapter {
viewHolder.itemView.setOnLongClickListener(view -> { itemClickListener.onMediaLongClicked(dcMsg); return true; });
viewHolder.itemView.setSelected(selected.contains(dcMsg));
viewHolder.date.setText(DateUtils.getBriefRelativeTimeSpanString(context, locale, dcMsg.getTimestamp()));
viewHolder.date.setText(DateUtils.getBriefRelativeTimeSpanString(context, dcMsg.getTimestamp()));
}
@Override

View file

@ -31,7 +31,6 @@ import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Locale;
import java.util.Set;
public class ProfileDocumentsFragment
@ -39,7 +38,6 @@ public class ProfileDocumentsFragment
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
ProfileDocumentsAdapter.ItemClickListener
{
public static final String LOCALE_EXTRA = "locale_extra";
public static final String CHAT_ID_EXTRA = "chat_id";
public static final String SHOW_AUDIO_EXTRA = "show_audio";
public static final String SHOW_WEBXDC_EXTRA = "show_webxdc";
@ -52,7 +50,6 @@ public class ProfileDocumentsFragment
private boolean showWebxdc;
protected int chatId;
protected Locale locale;
@Override
public void onCreate(Bundle bundle) {
@ -62,8 +59,6 @@ public class ProfileDocumentsFragment
chatId = getArguments().getInt(CHAT_ID_EXTRA, -1);
showAudio = getArguments().getBoolean(SHOW_AUDIO_EXTRA, false);
showWebxdc = getArguments().getBoolean(SHOW_WEBXDC_EXTRA, false);
locale = (Locale)getArguments().getSerializable(LOCALE_EXTRA);
if (locale == null) throw new AssertionError();
getLoaderManager().initLoader(0, null, this);
}
@ -78,7 +73,6 @@ public class ProfileDocumentsFragment
this.recyclerView.setAdapter(new ProfileDocumentsAdapter(getContext(),
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
locale,
this));
this.recyclerView.setLayoutManager(gridManager);
this.recyclerView.setHasFixedSize(true);

View file

@ -18,14 +18,12 @@ import org.thoughtcrime.securesms.util.MediaUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
class ProfileGalleryAdapter extends StickyHeaderGridAdapter {
private final Context context;
private final GlideRequests glideRequests;
private final Locale locale;
private final ItemClickListener itemClickListener;
private final Set<DcMsg> selected;
@ -54,12 +52,10 @@ class ProfileGalleryAdapter extends StickyHeaderGridAdapter {
ProfileGalleryAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
BucketedThreadMedia media,
Locale locale,
ItemClickListener clickListener)
{
this.context = context;
this.glideRequests = glideRequests;
this.locale = locale;
this.media = media;
this.itemClickListener = clickListener;
this.selected = new HashSet<>();
@ -81,7 +77,7 @@ class ProfileGalleryAdapter extends StickyHeaderGridAdapter {
@Override
public void onBindHeaderViewHolder(StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
((HeaderHolder)viewHolder).textView.setText(media.getName(section, locale));
((HeaderHolder)viewHolder).textView.setText(media.getName(section));
}
@Override

View file

@ -33,7 +33,6 @@ import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Locale;
import java.util.Set;
public class ProfileGalleryFragment
@ -41,7 +40,6 @@ public class ProfileGalleryFragment
implements LoaderManager.LoaderCallbacks<BucketedThreadMediaLoader.BucketedThreadMedia>,
ProfileGalleryAdapter.ItemClickListener
{
public static final String LOCALE_EXTRA = "locale_extra";
public static final String CHAT_ID_EXTRA = "chat_id";
protected TextView noMedia;
@ -50,7 +48,6 @@ public class ProfileGalleryFragment
private final ActionModeCallback actionModeCallback = new ActionModeCallback();
private int chatId;
private Locale locale;
@Override
public void onCreate(Bundle bundle) {
@ -58,8 +55,6 @@ public class ProfileGalleryFragment
dcContext = DcHelper.getContext(getContext());
chatId = getArguments().getInt(CHAT_ID_EXTRA, -1);
locale = (Locale)getArguments().getSerializable(LOCALE_EXTRA);
if (locale == null) throw new AssertionError();
getLoaderManager().initLoader(0, null, this);
}
@ -75,7 +70,6 @@ public class ProfileGalleryFragment
this.recyclerView.setAdapter(new ProfileGalleryAdapter(getContext(),
GlideApp.with(this),
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
locale,
this));
this.recyclerView.setLayoutManager(gridManager);
this.recyclerView.setHasFixedSize(true);

View file

@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public class ProfileSettingsAdapter extends RecyclerView.Adapter
@ -37,7 +36,6 @@ public class ProfileSettingsAdapter extends RecyclerView.Adapter
public static final int INFO_SEND_MESSAGE_BUTTON = 120;
private final @NonNull Context context;
private final @NonNull Locale locale;
private final @NonNull DcContext dcContext;
private final @NonNull ArrayList<ItemData> itemData = new ArrayList<>();
@ -87,13 +85,11 @@ public class ProfileSettingsAdapter extends RecyclerView.Adapter
public ProfileSettingsAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable ItemClickListener clickListener)
{
super();
this.context = context;
this.glideRequests = glideRequests;
this.locale = locale;
this.clickListener = clickListener;
this.dcContext = DcHelper.getContext(context);
this.layoutInflater = LayoutInflater.from(context);
@ -185,7 +181,7 @@ public class ProfileSettingsAdapter extends RecyclerView.Adapter
conversationListItem.bind(DcHelper.getThreadRecord(context, summary, chat),
itemDataSharedChats.getMsgId(chatlistIndex), summary, glideRequests,
locale, Collections.emptySet(), false);
Collections.emptySet(), false);
conversationListItem.setOnClickListener(view -> clickListener.onSharedChatClicked(chatId));
}
else if(holder.itemView instanceof ProfileStatusItem) {
@ -329,7 +325,7 @@ public class ProfileSettingsAdapter extends RecyclerView.Adapter
lastSeenTxt = context.getString(R.string.last_seen_unknown);
}
else {
lastSeenTxt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, locale, lastSeenTimestamp));
lastSeenTxt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp));
}
itemData.add(new ItemData(ItemData.CATEGORY_INFO, INFO_LAST_SEEN, lastSeenTxt, 0, 0));

View file

@ -39,12 +39,10 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
public class ProfileSettingsFragment extends Fragment
implements ProfileSettingsAdapter.ItemClickListener, DcEventCenter.DcEventDelegate {
public static final String LOCALE_EXTRA = "locale_extra";
public static final String CHAT_ID_EXTRA = "chat_id";
public static final String CONTACT_ID_EXTRA = "contact_id";
@ -57,7 +55,6 @@ public class ProfileSettingsFragment extends Fragment
private final ActionModeCallback actionModeCallback = new ActionModeCallback();
private Locale locale;
private DcContext dcContext;
protected int chatId;
private int contactId;
@ -70,8 +67,6 @@ public class ProfileSettingsFragment extends Fragment
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
locale = (Locale)getArguments().getSerializable(LOCALE_EXTRA);
if (locale == null) throw new AssertionError();
chatId = getArguments().getInt(CHAT_ID_EXTRA, -1);
contactId = getArguments().getInt(CONTACT_ID_EXTRA, -1);
dcContext = DcHelper.getContext(getContext());
@ -80,7 +75,7 @@ public class ProfileSettingsFragment extends Fragment
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.profile_settings_fragment, container, false);
adapter = new ProfileSettingsAdapter(getContext(), GlideApp.with(this), locale,this);
adapter = new ProfileSettingsAdapter(getContext(), GlideApp.with(this), this);
list = ViewUtil.findById(view, R.id.recycler_view);
list.setAdapter(adapter);

View file

@ -17,8 +17,6 @@ import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.DateUtils;
import java.util.Locale;
public class ConversationItemFooter extends LinearLayout {
private TextView dateView;
@ -58,8 +56,8 @@ public class ConversationItemFooter extends LinearLayout {
}
}
public void setMessageRecord(@NonNull DcMsg messageRecord, @NonNull Locale locale) {
presentDate(messageRecord, locale);
public void setMessageRecord(@NonNull DcMsg messageRecord) {
presentDate(messageRecord);
secureIndicatorView.setVisibility(messageRecord.isSecure() ? View.VISIBLE : View.GONE);
locationIndicatorView.setVisibility(messageRecord.hasLocation() ? View.VISIBLE : View.GONE);
presentDeliveryStatus(messageRecord);
@ -72,14 +70,9 @@ public class ConversationItemFooter extends LinearLayout {
deliveryStatusView.setTint(color);
}
private void presentDate(@NonNull DcMsg messageRecord, @NonNull Locale locale) {
private void presentDate(@NonNull DcMsg messageRecord) {
dateView.forceLayout();
// if(messageRecord.hasDeviatingTimestamp()) {
dateView.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
// }
// else {
// dateView.setText(DateUtils.getTimeOfDayTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
// }
dateView.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), messageRecord.getTimestamp()));
}
private void presentDeliveryStatus(@NonNull DcMsg messageRecord) {

View file

@ -11,6 +11,7 @@ import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Util;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -20,7 +21,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMediaLoader.BucketedThreadMedia> {
@ -147,11 +147,11 @@ public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMed
else return OLDER.getItem(section - activeTimeBuckets.size(), item);
}
public String getName(int section, Locale locale) {
public String getName(int section) {
List<TimeBucket> activeTimeBuckets = Stream.of(TIME_SECTIONS).filter(timeBucket -> !timeBucket.isEmpty()).toList();
if (section < activeTimeBuckets.size()) return activeTimeBuckets.get(section).getName();
else return OLDER.getName(section - activeTimeBuckets.size(), locale);
else return OLDER.getName(section - activeTimeBuckets.size());
}
// tests should override this function to deliver a preset calendar.
@ -266,10 +266,10 @@ public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMed
return keys.get(section);
}
String getName(int section, Locale locale) {
String getName(int section) {
Date sectionDate = getSection(section);
return new SimpleDateFormat("MMMM yyyy", locale).format(sectionDate);
return new SimpleDateFormat("MMMM yyyy", Util.getLocale()).format(sectionDate);
}
}
}

View file

@ -10,11 +10,9 @@ import androidx.preference.Preference;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.Prefs;
import java.util.Arrays;
import java.util.Locale;
public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment {
@ -23,9 +21,7 @@ public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment
super.onCreate(paramBundle);
this.findPreference(Prefs.THEME_PREF).setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(Prefs.LANGUAGE_PREF).setOnPreferenceChangeListener(new ListSummaryListener());
initializeListSummary((ListPreference)findPreference(Prefs.THEME_PREF));
initializeListSummary((ListPreference)findPreference(Prefs.LANGUAGE_PREF));
this.findPreference(Prefs.BACKGROUND_PREF).setOnPreferenceClickListener(new BackgroundClickListener());
this.findPreference(Prefs.MESSAGE_BODY_TEXT_SIZE_PREF).setOnPreferenceChangeListener(new ListSummaryListener());
initializeListSummary((ListPreference) findPreference(Prefs.MESSAGE_BODY_TEXT_SIZE_PREF));
@ -61,12 +57,6 @@ public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment
public void onStop() {
super.onStop();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener((ApplicationPreferencesActivity) getActivity());
// update the locale of the applicationContext so that the core gets the correct strings
// (for pending activities, the locale is updated by calling DynamicLanguage.onResume)
Context applicationContext = this.getActivity().getApplicationContext();
DynamicLanguage.setContextLocale(applicationContext, DynamicLanguage.getSelectedLocale(applicationContext));
DcHelper.setStockTranslations(applicationContext);
}
public static CharSequence getSummary(Context context) {
@ -84,25 +74,11 @@ public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment
backgroundString = context.getString(R.string.custom);
}
String[] languageEntries = context.getResources().getStringArray(R.array.language_entries);
String[] languageEntryValues = context.getResources().getStringArray(R.array.language_values);
int langIndex = Arrays.asList(languageEntryValues).indexOf(Prefs.getLanguage(context));
if(langIndex==0) {
Locale locale = DynamicLanguage.getSelectedLocale(context);
String localeAbbr = locale.getLanguage();
langIndex = Arrays.asList(languageEntryValues).indexOf(localeAbbr);
if(langIndex==-1 && localeAbbr.length()>2) {
langIndex = Arrays.asList(languageEntryValues).indexOf(localeAbbr.substring(0,2));
}
}
if (langIndex == -1) langIndex = 0;
// adding combined strings as "Read receipt: %1$s, Screen lock: %1$s, "
// makes things inflexible on changes and/or adds lot of additional works to programmers.
// however, if needed, we can refine this later.
return themeEntries[themeIndex] + ", "
+ context.getString(R.string.pref_background) + " " + backgroundString + ", "
+ languageEntries[langIndex];
+ context.getString(R.string.pref_background) + " " + backgroundString;
}
private class BackgroundClickListener implements Preference.OnPreferenceClickListener {

View file

@ -18,8 +18,8 @@ import com.b44t.messenger.DcEvent;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Util;
import java.util.Locale;
public class BackupReceiverFragment extends Fragment implements DcEventCenter.DcEventDelegate {
@ -87,7 +87,7 @@ public class BackupReceiverFragment extends Fragment implements DcEventCenter.Dc
} else if (permille <= 950 ) {
percent = ((permille-100)*100)/850;
percentMax = 100;
statusLineText = getString(R.string.transferring) + String.format(Locale.getDefault(), " %d%%", percent);
statusLineText = getString(R.string.transferring) + String.format(Util.getLocale(), " %d%%", percent);
hideSameNetworkHint = true;
} else if (permille < 1000) {
statusLineText = "Finishing..."; // range not used, should not happen

View file

@ -73,11 +73,11 @@ public class BackupTransferActivity extends BaseActionBarActivity {
switch(transferMode) {
case SENDER_SHOW_QR:
initFragment(android.R.id.content, new BackupProviderFragment(), dynamicLanguage.getCurrentLocale(), icicle);
initFragment(android.R.id.content, new BackupProviderFragment(), icicle);
break;
case RECEIVER_SCAN_QR:
initFragment(android.R.id.content, new BackupReceiverFragment(), dynamicLanguage.getCurrentLocale(), icicle);
initFragment(android.R.id.content, new BackupReceiverFragment(), icicle);
break;
}

View file

@ -12,13 +12,11 @@ import com.b44t.messenger.DcContext;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
public class QrShowActivity extends AppCompatActivity {
private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
public final static String CHAT_ID = "chat_id";
@ -31,7 +29,6 @@ public class QrShowActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this);
setContentView(R.layout.activity_qr_show);
fragment = (QrShowFragment)getSupportFragmentManager().findFragmentById(R.id.qrScannerFragment);
@ -78,7 +75,6 @@ public class QrShowActivity extends AppCompatActivity {
protected void onResume() {
super.onResume();
dynamicTheme.onResume(this);
dynamicLanguage.onResume(this);
}
@Override

View file

@ -36,7 +36,6 @@ import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.search.model.SearchResult;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import java.util.Locale;
import java.util.Set;
/**
@ -46,7 +45,6 @@ public class SearchFragment extends BaseConversationListFragment
implements SearchListAdapter.EventListener, DcEventCenter.DcEventDelegate {
public static final String TAG = "SearchFragment";
public static final String EXTRA_LOCALE = "locale";
private TextView noResultsView;
private RecyclerView listView;
@ -55,11 +53,9 @@ public class SearchFragment extends BaseConversationListFragment
private SearchViewModel viewModel;
private SearchListAdapter listAdapter;
private String pendingQuery;
private Locale locale;
public static SearchFragment newInstance(@NonNull Locale locale) {
public static SearchFragment newInstance() {
Bundle args = new Bundle();
args.putSerializable(EXTRA_LOCALE, locale);
SearchFragment fragment = new SearchFragment();
fragment.setArguments(args);
@ -71,8 +67,6 @@ public class SearchFragment extends BaseConversationListFragment
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.locale = (Locale) getArguments().getSerializable(EXTRA_LOCALE);
viewModel = ViewModelProviders.of(this, (ViewModelProvider.Factory) new SearchViewModel.Factory(requireContext())).get(SearchViewModel.class);
DcEventCenter eventCenter = DcHelper.getEventCenter(requireContext());
eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
@ -102,7 +96,7 @@ public class SearchFragment extends BaseConversationListFragment
listView = view.findViewById(R.id.search_list);
fab = view.findViewById(R.id.fab);
listAdapter = new SearchListAdapter(getContext(), GlideApp.with(this), this, locale);
listAdapter = new SearchListAdapter(getContext(), GlideApp.with(this), this);
listDecoration = new StickyHeaderDecoration(listAdapter, false, true);
fab.setVisibility(View.GONE);

View file

@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.search.model.SearchResult;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import java.util.Locale;
import java.util.Set;
class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.SearchResultViewHolder>
@ -36,7 +35,6 @@ class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.Se
private final GlideRequests glideRequests;
private final EventListener eventListener;
private final Locale locale;
@NonNull
private SearchResult searchResult = SearchResult.EMPTY;
@ -46,12 +44,10 @@ class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.Se
SearchListAdapter(Context context,
@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener,
@NonNull Locale locale)
@NonNull EventListener eventListener)
{
this.glideRequests = glideRequests;
this.eventListener = eventListener;
this.locale = locale;
this.context = context;
this.dcContext = DcHelper.getContext(context);
}
@ -68,21 +64,21 @@ class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.Se
DcChatlist.Item conversationResult = getConversationResult(position);
if (conversationResult != null) {
holder.bind(context, conversationResult, glideRequests, eventListener, locale, batchSet, batchMode, searchResult.getQuery());
holder.bind(context, conversationResult, glideRequests, eventListener, batchSet, batchMode, searchResult.getQuery());
return;
}
DcContact contactResult = getContactResult(position);
if (contactResult != null) {
holder.bind(contactResult, glideRequests, eventListener, locale, searchResult.getQuery());
holder.bind(contactResult, glideRequests, eventListener, searchResult.getQuery());
return;
}
DcMsg messageResult = getMessageResult(position);
if (messageResult != null) {
holder.bind(messageResult, glideRequests, eventListener, locale, searchResult.getQuery());
holder.bind(messageResult, glideRequests, eventListener, searchResult.getQuery());
}
}
@ -208,14 +204,13 @@ class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.Se
@NonNull DcChatlist.Item chatlistItem,
@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener,
@NonNull Locale locale,
@NonNull Set<Long> selectedThreads,
boolean batchMode,
@Nullable String query)
{
DcContext dcContext = DcHelper.getContext(context);
ThreadRecord threadRecord = DcHelper.getThreadRecord(context, chatlistItem.summary, dcContext.getChat(chatlistItem.chatId));
root.bind(threadRecord, chatlistItem.msgId, chatlistItem.summary, glideRequests, locale, selectedThreads, batchMode, query);
root.bind(threadRecord, chatlistItem.msgId, chatlistItem.summary, glideRequests, selectedThreads, batchMode, query);
root.setOnClickListener(view -> eventListener.onConversationClicked(chatlistItem));
root.setOnLongClickListener(view -> {
eventListener.onConversationLongClicked(chatlistItem);
@ -226,20 +221,18 @@ class SearchListAdapter extends BaseConversationListAdapter<SearchListAdapter.Se
void bind(@NonNull DcContact contactResult,
@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener,
@NonNull Locale locale,
@Nullable String query)
{
root.bind(contactResult, glideRequests, locale, query);
root.bind(contactResult, glideRequests, query);
root.setOnClickListener(view -> eventListener.onContactClicked(contactResult));
}
void bind(@NonNull DcMsg messageResult,
@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener,
@NonNull Locale locale,
@Nullable String query)
{
root.bind(messageResult, glideRequests, locale, query);
root.bind(messageResult, glideRequests, query);
root.setOnClickListener(view -> eventListener.onMessageClicked(messageResult));
}

View file

@ -93,7 +93,7 @@ public final class GenericForegroundService extends Service {
private synchronized void handleStart(@NonNull Intent intent) {
Entry entry = Entry.fromIntent(intent);
Log.i(TAG, String.format(Locale.US, "handleStart() %s", entry));
Log.i(TAG, String.format(Locale.ENGLISH, "handleStart() %s", entry));
allActiveMessages.put(entry.id, entry);
}
@ -240,7 +240,7 @@ public final class GenericForegroundService extends Service {
@Override
public @NonNull String toString() {
return String.format(Locale.US, "ChannelId: %s Id: %d Progress: %d/%d %s", channelId, id, progress, progressMax, indeterminate ? "indeterminate" : "determinate");
return String.format(Locale.ENGLISH, "ChannelId: %s Id: %d Progress: %d/%d %s", channelId, id, progress, progressMax, indeterminate ? "indeterminate" : "determinate");
}
@Override

View file

@ -25,7 +25,6 @@ import org.thoughtcrime.securesms.R;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
/**
@ -45,9 +44,9 @@ public class DateUtils extends android.text.format.DateUtils {
return (int) to.convert(System.currentTimeMillis() - millis, TimeUnit.MILLISECONDS);
}
private static String getFormattedDateTime(long time, String template, Locale locale) {
final String localizedPattern = getLocalizedPattern(template, locale);
String ret = new SimpleDateFormat(localizedPattern, locale).format(new Date(time));
private static String getFormattedDateTime(long time, String template) {
final String localizedPattern = getLocalizedPattern(template);
String ret = new SimpleDateFormat(localizedPattern).format(new Date(time));
// having ".," in very common and known abbreviates as weekdays or month names is not needed,
// looks ugly and makes the string longer than needed
@ -56,7 +55,7 @@ public class DateUtils extends android.text.format.DateUtils {
return ret;
}
public static String getBriefRelativeTimeSpanString(final Context c, final Locale locale, final long timestamp) {
public static String getBriefRelativeTimeSpanString(final Context c, final long timestamp) {
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
return c.getString(R.string.now);
} else if (isWithin(timestamp, 1, TimeUnit.HOURS)) {
@ -66,15 +65,15 @@ public class DateUtils extends android.text.format.DateUtils {
int hours = convertDelta(timestamp, TimeUnit.HOURS);
return c.getResources().getQuantityString(R.plurals.n_hours, hours, hours);
} else if (isWithin(timestamp, 6, TimeUnit.DAYS)) {
return getFormattedDateTime(timestamp, "EEE", locale);
return getFormattedDateTime(timestamp, "EEE");
} else if (isWithin(timestamp, 365, TimeUnit.DAYS)) {
return getFormattedDateTime(timestamp, "MMM d", locale);
return getFormattedDateTime(timestamp, "MMM d");
} else {
return getFormattedDateTime(timestamp, "MMM d, yyyy", locale);
return getFormattedDateTime(timestamp, "MMM d, yyyy");
}
}
public static String getExtendedTimeSpanString(final Context c, final Locale locale, final long timestamp) {
public static String getExtendedTimeSpanString(final Context c, final long timestamp) {
StringBuilder format = new StringBuilder();
if (DateUtils.isToday(timestamp)) {}
else if (isWithin(timestamp, 6, TimeUnit.DAYS)) format.append("EEE ");
@ -84,22 +83,21 @@ public class DateUtils extends android.text.format.DateUtils {
if (DateFormat.is24HourFormat(c)) format.append("HH:mm");
else format.append("hh:mm a");
return getFormattedDateTime(timestamp, format.toString(), locale);
return getFormattedDateTime(timestamp, format.toString());
}
public static String getExtendedRelativeTimeSpanString(final Context c, final Locale locale, final long timestamp) {
public static String getExtendedRelativeTimeSpanString(final Context c, final long timestamp) {
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
return c.getString(R.string.now);
} else if (isWithin(timestamp, 1, TimeUnit.HOURS)) {
int mins = (int)TimeUnit.MINUTES.convert(System.currentTimeMillis() - timestamp, TimeUnit.MILLISECONDS);
return c.getResources().getQuantityString(R.plurals.n_minutes, mins, mins);
} else {
return getExtendedTimeSpanString(c, locale, timestamp);
return getExtendedTimeSpanString(c, timestamp);
}
}
public static String getRelativeDate(@NonNull Context context,
@NonNull Locale locale,
long timestamp)
{
if (isToday(timestamp)) {
@ -107,15 +105,15 @@ public class DateUtils extends android.text.format.DateUtils {
} else if (isYesterday(timestamp)) {
return context.getString(R.string.yesterday);
} else {
return getFormattedDateTime(timestamp, "EEEE, MMMM d, yyyy", locale);
return getFormattedDateTime(timestamp, "EEEE, MMMM d, yyyy");
}
}
private static String getLocalizedPattern(String template, Locale locale) {
private static String getLocalizedPattern(String template) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return DateFormat.getBestDateTimePattern(locale, template);
return DateFormat.getBestDateTimePattern(Util.getLocale(), template);
} else {
return new SimpleDateFormat(template, locale).toLocalizedPattern();
return new SimpleDateFormat(template, Util.getLocale()).toLocalizedPattern();
}
}

View file

@ -1,106 +0,0 @@
package org.thoughtcrime.securesms.util;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.core.os.ConfigurationCompat;
import androidx.core.view.ViewCompat;
import android.text.TextUtils;
import android.util.Log;
import java.util.Locale;
public class DynamicLanguage {
private static final String TAG = DynamicLanguage.class.getSimpleName();
private static final String DEFAULT = "zz";
private Locale currentLocale;
public void onCreate(Activity activity) {
currentLocale = getSelectedLocale(activity);
setContextLocale(activity, currentLocale);
}
public void onResume(Activity activity) {
if (!getSelectedLocale(activity).equals(currentLocale)) {
Intent intent = activity.getIntent();
activity.finish();
OverridePendingTransition.invoke(activity);
activity.startActivity(intent);
OverridePendingTransition.invoke(activity);
}
}
public void updateServiceLocale(Service service) {
currentLocale = getSelectedLocale(service);
setContextLocale(service, currentLocale);
}
public Locale getCurrentLocale() {
return currentLocale;
}
public static int getLayoutDirection(Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = context.getResources().getConfiguration();
return configuration.getLayoutDirection();
}
return ViewCompat.LAYOUT_DIRECTION_LTR;
}
public static void setContextLocale(Context context, Locale selectedLocale) {
Configuration configuration = context.getResources().getConfiguration();
if (!configuration.locale.equals(selectedLocale)) {
configuration.locale = selectedLocale;
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(selectedLocale);
}
context.getResources().updateConfiguration(configuration,
context.getResources().getDisplayMetrics());
}
}
private static Locale getActivityLocale(Activity activity) {
return activity.getResources().getConfiguration().locale;
}
// Beware that Locale.getDefault() returns the locale the App was STARTED in, not the locale of the system.
// It just happens to be the same for the majority of use cases.
private static Locale getDefaultLocale() {
Locale locale = null;
try {
locale = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration()).get(0);
} catch(Exception e) {
Log.e(TAG, "could not determine the system locale.", e);
}
return locale != null ? locale : Locale.getDefault();
}
public static Locale getSelectedLocale(Context context) {
String language[] = TextUtils.split(Prefs.getLanguage(context), "_");
if (language[0].equals(DEFAULT)) {
return getDefaultLocale();
} else if (language.length == 2) {
return new Locale(language[0], language[1]);
} else {
return new Locale(language[0]);
}
}
private static final class OverridePendingTransition {
static void invoke(Activity activity) {
activity.overridePendingTransition(0, 0);
}
}
}

View file

@ -31,7 +31,6 @@ public class Prefs {
public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase";
public static final String THEME_PREF = "pref_theme";
public static final String LANGUAGE_PREF = "pref_language";
public static final String BACKGROUND_PREF = "pref_chat_background";
private static final String DATABASE_ENCRYPTED_SECRET = "pref_database_encrypted_secret_"; // followed by account-id
@ -151,14 +150,6 @@ public class Prefs {
return getStringPreference(context, THEME_PREF, DynamicTheme.systemThemeAvailable() ? DynamicTheme.SYSTEM : DynamicTheme.LIGHT);
}
public static String getLanguage(Context context) {
return getStringPreference(context, LANGUAGE_PREF, "zz");
}
public static void setLanguage(Context context, String language) {
setStringPreference(context, LANGUAGE_PREF, language);
}
public static void setPromptedDozeMsgId(Context context, int msg_id) {
setIntegerPreference(context, PROMPTED_DOZE_MSG_ID_PREF, msg_id);
}

View file

@ -261,7 +261,7 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTa
} else {
String dir = getExternalPathForType(contentType);
if (dir == null) {
throw new IOException(String.format(Locale.US, "Path for type: %s was not available", contentType));
throw new IOException(String.format(Locale.ENGLISH, "Path for type: %s was not available", contentType));
}
String outputFileName = fileName;

View file

@ -21,6 +21,8 @@ import android.app.ActivityManager;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
@ -42,6 +44,8 @@ import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.os.ConfigurationCompat;
import androidx.core.view.ViewCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.ComposeText;
@ -54,6 +58,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
@ -357,4 +362,34 @@ public class Util {
return false;
}
}
private static Locale lastLocale = null;
public synchronized static Locale getLocale() {
if (lastLocale == null) {
try {
lastLocale = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration()).get(0);
} catch (Exception e) {
e.printStackTrace();
}
if (lastLocale == null) {
// Locale.getDefault() returns the locale the App was STARTED in, not the locale of the system.
// It just happens to be the same for the majority of use cases.
lastLocale = Locale.getDefault();
}
}
return lastLocale;
}
public synchronized static void localeChanged() {
lastLocale = null;
}
public static int getLayoutDirection(Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = context.getResources().getConfiguration();
return configuration.getLayoutDirection();
}
return ViewCompat.LAYOUT_DIRECTION_LTR;
}
}

View file

@ -162,7 +162,7 @@ public class ViewUtil {
@SuppressLint("RtlHardcoded")
public static void setTextViewGravityStart(final @NonNull TextView textView, @NonNull Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
if (DynamicLanguage.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
textView.setGravity(Gravity.RIGHT);
} else {
textView.setGravity(Gravity.LEFT);
@ -172,7 +172,7 @@ public class ViewUtil {
public static void mirrorIfRtl(View view, Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1 &&
DynamicLanguage.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
view.setScaleX(-1.0f);
}
}
@ -182,7 +182,7 @@ public class ViewUtil {
}
public static boolean isLtr(@NonNull Context context) {
return DynamicLanguage.getLayoutDirection(context) == ViewCompat.LAYOUT_DIRECTION_LTR;
return Util.getLayoutDirection(context) == ViewCompat.LAYOUT_DIRECTION_LTR;
}
public static boolean isRtl(@NonNull View view) {
@ -190,7 +190,7 @@ public class ViewUtil {
}
public static boolean isRtl(@NonNull Context context) {
return DynamicLanguage.getLayoutDirection(context) == ViewCompat.LAYOUT_DIRECTION_RTL;
return Util.getLayoutDirection(context) == ViewCompat.LAYOUT_DIRECTION_RTL;
}
public static int dpToPx(Context context, int dp) {

View file

@ -0,0 +1,2 @@
unqualifiedResLocale=en

View file

@ -1,108 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- take care, language_entries and languages_values are in sync ...
... some one has to clean up this mess some day ... -->
<string-array name="language_entries">
<!-- English name: Local name: -->
<!-- zz --> <item>@string/def</item>
<!-- az Azerbaijani --> <item>Azeri</item>
<!-- in Indonesian --> <item>Bahasa Indonesia</item>
<!-- ca Catalan --> <item>Català</item>
<!-- cs Czech --> <item>Čeština</item>
<!-- da Danish --> <item>Dansk</item>
<!-- de German --> <item>Deutsch</item>
<!-- en English --> <item>English</item>
<!-- es Spanish --> <item>Español</item>
<!-- eo Esperanto --> <item>Esperanto</item>
<!-- eu Basque --> <item>Euskara</item>
<!-- fr French --> <item>Français</item>
<!-- gl Galician --> <item>Galego</item>
<!-- hr Croatian --> <item>Hrvatski</item>
<!-- it Italian --> <item>Italiano</item>
<!-- lt Lithuanian --> <item>Lietuvių kalba</item>
<!-- bqi Bakhtiari --> <item>Luri Bakhtiari</item>
<!-- hu Hungarian --> <item>Magyar nyelv</item>
<!-- nl Dutch --> <item>Nederlands</item>
<!-- nb Norwegian Bokmål --> <item>Norsk Bokmål</item>
<!-- pl Polish --> <item>Polski</item>
<!-- pt Portuguese --> <item>Português</item>
<!-- pt_BR Portuguese (Brazil) --> <item>Português do Brasil</item>
<!-- ro Romanian --> <item>Română</item>
<!-- sc Sardinian --> <item>Sardu</item>
<!-- sq Albanian --> <item>Shqip</item>
<!-- sk Slovak --> <item>Slovenčina</item>
<!-- fi Finnish --> <item>Suomi</item>
<!-- sv Swedish --> <item>Svenska</item>
<!-- vi Vietnamese --> <item>Tiếng Việt</item>
<!-- tr Turkish --> <item>Türkçe</item>
<!-- el Greek --> <item>Ελληνικά</item>
<!-- ru Russian --> <item>Pусский</item>
<!-- sr Serbian --> <item>Српски</item>
<!-- uk Ukrainian --> <item>Українська</item>
<!-- bg Bulgarian --> <item>Български</item>
<!-- ar Arabic --> <item>العربیة</item>
<!-- fa Persian/Farsi --> <item>فارسی</item>
<!-- ckb Central Kurdish/Sorani --> <item>کوردی</item>
<!-- ja Japanese --> <item>日本語</item>
<!-- ko Korean --> <item>한국어</item>
<!-- zh_CN Chinese traditional --> <item>简体中文</item>
<!-- zh_TW Chinese trad. (Taiwan) --> <item>繁體中文</item>
<!-- km Khmer --> <item>ភាសាខ្មែរ</item>
<!-- ta Tamil --> <item>தமிழ்</item>
<!-- te Telugu --> <item>తెలుగు</item>
</string-array>
<string-array name="language_values">
<item>zz</item>
<item>az</item>
<item>in</item> <!-- sic: Android uses "in" where ISO 639-1 is "id" -->
<item>ca</item>
<item>cs</item>
<item>da</item>
<item>de</item>
<item>en</item>
<item>es</item>
<item>eo</item>
<item>eu</item>
<item>fr</item>
<item>gl</item>
<item>hr</item>
<item>it</item>
<item>lt</item>
<item>bqi</item>
<item>hu</item>
<item>nl</item>
<item>nb</item>
<item>pl</item>
<item>pt</item>
<item>pt_BR</item>
<item>ro</item>
<item>sc</item>
<item>sq</item>
<item>sk</item>
<item>fi</item>
<item>sv</item>
<item>vi</item>
<item>tr</item>
<item>el</item>
<item>ru</item>
<item>sr</item>
<item>uk</item>
<item>bg</item>
<item>ar</item>
<item>fa</item>
<item>ckb</item>
<item>ja</item>
<item>ko</item>
<item>zh_CN</item>
<item>zh_TW</item>
<item>km</item>
<item>ta</item>
<item>te</item>
</string-array>
<!-- "InconsistentArrays" is needed as the array is duplicated in values-v29/arrays.xml with a different size -->
<string-array name="pref_theme_entries" tools:ignore="InconsistentArrays">
<item>@string/pref_light_theme</item>

View file

@ -28,11 +28,4 @@
android:title="@string/pref_use_system_emoji"
android:summary="@string/pref_use_system_emoji_explain" />
<ListPreference
android:key="pref_language"
android:title="@string/pref_language"
android:entries="@array/language_entries"
android:entryValues="@array/language_values"
android:defaultValue="zz"/>
</PreferenceScreen>

View file

@ -28,11 +28,4 @@
android:title="@string/pref_use_system_emoji"
android:summary="@string/pref_use_system_emoji_explain" />
<ListPreference
android:key="pref_language"
android:title="@string/pref_language"
android:entries="@array/language_entries"
android:entryValues="@array/language_values"
android:defaultValue="zz"/>
</PreferenceScreen>