diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb
index c42c4c23efc44c267cde810ed3c183d70b159737..ddb10aa25f519627d69e6b813817eba6e5420c1b 100644
--- a/app/helpers/languages_helper.rb
+++ b/app/helpers/languages_helper.rb
@@ -230,6 +230,24 @@ module LanguagesHelper
     'sr-Latn': 'Srpski (latinica)',
   }.freeze
 
+  # Helper for self.sorted_locale_keys
+  private_class_method def self.locale_name_for_sorting(locale)
+    if locale.blank? || locale == 'und'
+      '000'
+    elsif (supported_locale = SUPPORTED_LOCALES[locale.to_sym])
+      ASCIIFolding.new.fold(supported_locale[1]).downcase
+    elsif (regional_locale = REGIONAL_LOCALE_NAMES[locale.to_sym])
+      ASCIIFolding.new.fold(regional_locale).downcase
+    else
+      locale
+    end
+  end
+
+  # Sort locales by native name for dropdown menus
+  def self.sorted_locale_keys(locale_keys)
+    locale_keys.sort_by { |key, _| locale_name_for_sorting(key) }
+  end
+
   def native_locale_name(locale)
     if locale.blank? || locale == 'und'
       I18n.t('generic.none')
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 889ca7f402def0be295d5e19e06ac0e0e45693b8..fce36bf43e99d0776dffaa7a7bedef374443a2e7 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -2,7 +2,11 @@
 
 module SettingsHelper
   def filterable_languages
-    LanguagesHelper::SUPPORTED_LOCALES.keys
+    LanguagesHelper.sorted_locale_keys(LanguagesHelper::SUPPORTED_LOCALES.keys)
+  end
+
+  def ui_languages
+    LanguagesHelper.sorted_locale_keys(I18n.available_locales)
   end
 
   def session_device_icon(session)
diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml
index ea33487c3cf909f06b52091c20583313cdbabc82..11fa2bfc435d786467e57b502627ec15b19edb4a 100644
--- a/app/views/settings/preferences/appearance/show.html.haml
+++ b/app/views/settings/preferences/appearance/show.html.haml
@@ -7,7 +7,7 @@
 = simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f|
   .fields-row
     .fields-group.fields-row__column.fields-row__column-6
-      = f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, selected: I18n.locale, hint: false
+      = f.input :locale, collection: ui_languages, wrapper: :with_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, selected: I18n.locale, hint: false
     .fields-group.fields-row__column.fields-row__column-6
       = f.input :time_zone, wrapper: :with_label, collection: ActiveSupport::TimeZone.all.map { |tz| ["(GMT#{tz.formatted_offset}) #{tz.name}", tz.tzinfo.name] }, hint: false
 
diff --git a/spec/helpers/languages_helper_spec.rb b/spec/helpers/languages_helper_spec.rb
index 98c8064a3355d1395840f3ad72b213e1e3bf6a7c..99461b293ba6f976f43ceb56b0911eeaa53fe43a 100644
--- a/spec/helpers/languages_helper_spec.rb
+++ b/spec/helpers/languages_helper_spec.rb
@@ -60,4 +60,30 @@ describe LanguagesHelper do
       end
     end
   end
+
+  describe 'sorted_locales' do
+    context 'when sorting with native name' do
+      it 'returns Suomi after Gàidhlig' do
+        expect(described_class.sorted_locale_keys(%w(fi gd))).to eq(%w(gd fi))
+      end
+    end
+
+    context 'when sorting with diacritics' do
+      it 'returns Íslensk before Suomi' do
+        expect(described_class.sorted_locale_keys(%w(fi is))).to eq(%w(is fi))
+      end
+    end
+
+    context 'when sorting with non-Latin' do
+      it 'returns Suomi before Amharic' do
+        expect(described_class.sorted_locale_keys(%w(am fi))).to eq(%w(fi am))
+      end
+    end
+
+    context 'when sorting with local variants' do
+      it 'returns variant in-line' do
+        expect(described_class.sorted_locale_keys(%w(en eo en-GB))).to eq(%w(en en-GB eo))
+      end
+    end
+  end
 end