diff --git a/localizely.yml b/localizely.yml
index 86b4b077d8..76feea21eb 100644
--- a/localizely.yml
+++ b/localizely.yml
@@ -1,78 +1,94 @@
-config_version: 1.0
-project_id: ead34689-ec52-41d9-b675-09bc85a6cbd7
-file_type: json
-branch: main
-upload:
-  files:
-    - file: mobile/assets/i18n/en-US.json
-      locale_code: en-US
-download:
-  params:
-    export_empty_as: main
-  files:
-    - file: mobile/assets/i18n/en-US.json
-      locale_code: en-US
-    - file: mobile/assets/i18n/de-DE.json
-      locale_code: de-DE
-    - file: mobile/assets/i18n/da-DK.json
-      locale_code: da-DK
-    - file: mobile/assets/i18n/it-IT.json
-      locale_code: it-IT
-    - file: mobile/assets/i18n/es-ES.json
-      locale_code: es-ES
-    - file: mobile/assets/i18n/vi-VN.json
-      locale_code: vi-VN
-    - file: mobile/assets/i18n/fr-FR.json
-      locale_code: fr-FR
-    - file: mobile/assets/i18n/ja-JP.json
-      locale_code: ja-JP
-    - file: mobile/assets/i18n/pl-PL.json
-      locale_code: pl-PL
-    - file: mobile/assets/i18n/fi-FI.json
-      locale_code: fi-FI
-    - file: mobile/assets/i18n/pt-PT.json
-      locale_code: pt-PT
-    - file: mobile/assets/i18n/pt-BR.json
-      locale_code: pt-BR
-    - file: mobile/assets/i18n/cs-CZ.json
-      locale_code: cs-CZ
-    - file: mobile/assets/i18n/uk-UA.json
-      locale_code: uk-UA
-    - file: mobile/assets/i18n/ru-RU.json
-      locale_code: ru-RU
-    - file: mobile/assets/i18n/zh-CN.json
-      locale_code: zh-CN
-    - file: mobile/assets/i18n/sk-SK.json
-      locale_code: sk-SK
-    - file: mobile/assets/i18n/nl-NL.json
-      locale_code: nl-NL
-    - file: mobile/assets/i18n/nb-NO.json
-      locale_code: nb-NO
-    - file: mobile/assets/i18n/sv-SE.json
-      locale_code: sv-SE
-    - file: mobile/assets/i18n/mn.json
-      locale_code: mn
-    - file: mobile/assets/i18n/ko-KR.json
-      locale_code: ko-KR
-    - file: mobile/assets/i18n/sr-Latn.json
-      locale_code: sr-Latn
-    - file: mobile/assets/i18n/sr-Cyrl.json
-      locale_code: sr-Cyrl
-    - file: mobile/assets/i18n/hi-IN.json
-      locale_code: hi-IN
-    - file: mobile/assets/i18n/es-PE.json
-      locale_code: es-PE
-    - file: mobile/assets/i18n/es-MX.json
-      locale_code: es-MX
-    - file: mobile/assets/i18n/sv-FI.json
-      locale_code: sv-FI
-    - file: mobile/assets/i18n/ca.json
-      locale_code: ca
-    - file: mobile/assets/i18n/hu-HU.json
-      locale_code: hu-HU
-    - file: mobile/assets/i18n/lv-LV.json
-      locale_code: lv-LV
-    - file: mobile/assets/i18n/zh-Hans.json
-      locale_code: zh-Hans
-    - file: mobile/assets/i18n/th-TH.json
-      locale_code: th-TH
+config_version: 1.0
+project_id: ead34689-ec52-41d9-b675-09bc85a6cbd7
+file_type: json
+branch: main
+upload:
+  files:
+    - file: mobile/assets/i18n/en-US.json
+      locale_code: en-US
+download:
+  params:
+    export_empty_as: main
+  files:
+    - file: mobile/assets/i18n/en-US.json
+      locale_code: en-US
+    - file: mobile/assets/i18n/de-DE.json
+      locale_code: de-DE
+    - file: mobile/assets/i18n/da-DK.json
+      locale_code: da-DK
+    - file: mobile/assets/i18n/it-IT.json
+      locale_code: it-IT
+    - file: mobile/assets/i18n/es-ES.json
+      locale_code: es-ES
+    - file: mobile/assets/i18n/vi-VN.json
+      locale_code: vi-VN
+    - file: mobile/assets/i18n/fr-FR.json
+      locale_code: fr-FR
+    - file: mobile/assets/i18n/ja-JP.json
+      locale_code: ja-JP
+    - file: mobile/assets/i18n/pl-PL.json
+      locale_code: pl-PL
+    - file: mobile/assets/i18n/fi-FI.json
+      locale_code: fi-FI
+    - file: mobile/assets/i18n/pt-PT.json
+      locale_code: pt-PT
+    - file: mobile/assets/i18n/pt-BR.json
+      locale_code: pt-BR
+    - file: mobile/assets/i18n/cs-CZ.json
+      locale_code: cs-CZ
+    - file: mobile/assets/i18n/uk-UA.json
+      locale_code: uk-UA
+    - file: mobile/assets/i18n/ru-RU.json
+      locale_code: ru-RU
+    - file: mobile/assets/i18n/zh-CN.json
+      locale_code: zh-CN
+    - file: mobile/assets/i18n/sk-SK.json
+      locale_code: sk-SK
+    - file: mobile/assets/i18n/nl-NL.json
+      locale_code: nl-NL
+    - file: mobile/assets/i18n/nb-NO.json
+      locale_code: nb-NO
+    - file: mobile/assets/i18n/sv-SE.json
+      locale_code: sv-SE
+    - file: mobile/assets/i18n/mn.json
+      locale_code: mn
+    - file: mobile/assets/i18n/ko-KR.json
+      locale_code: ko-KR
+    - file: mobile/assets/i18n/sr-Latn.json
+      locale_code: sr-Latn
+    - file: mobile/assets/i18n/sr-Cyrl.json
+      locale_code: sr-Cyrl
+    - file: mobile/assets/i18n/hi-IN.json
+      locale_code: hi-IN
+    - file: mobile/assets/i18n/es-PE.json
+      locale_code: es-PE
+    - file: mobile/assets/i18n/es-MX.json
+      locale_code: es-MX
+    - file: mobile/assets/i18n/sv-FI.json
+      locale_code: sv-FI
+    - file: mobile/assets/i18n/ca-CA.json
+      locale_code: ca-CA
+    - file: mobile/assets/i18n/hu-HU.json
+      locale_code: hu-HU
+    - file: mobile/assets/i18n/lv-LV.json
+      locale_code: lv-LV
+    - file: mobile/assets/i18n/zh-Hans.json
+      locale_code: zh-Hans
+    - file: mobile/assets/i18n/th-TH.json
+      locale_code: th-TH
+    - file: mobile/assets/i18n/lt-LT.json
+      locale_code: lt-LT
+    - file: mobile/assets/i18n/el-GR.json
+      locale_code: el-GR
+    - file: mobile/assets/i18n/fr-CA.json
+      locale_code: fr-CA
+    - file: mobile/assets/i18n/es-US.json
+      locale_code: es-US
+    - file: mobile/assets/i18n/sl-SI.json
+      locale_code: sl-SI
+    - file: mobile/assets/i18n/ar-JO.json
+      locale_code: ar-JO
+    - file: mobile/assets/i18n/he-IL.json
+      locale_code: he-IL
+    - file: mobile/assets/i18n/ro-RO.json
+      locale_code: ro-RO
diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json
index f9ac99edb3..4975f866fd 100644
--- a/mobile/assets/i18n/en-US.json
+++ b/mobile/assets/i18n/en-US.json
@@ -400,7 +400,9 @@
   "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
   "setting_notifications_total_progress_title": "Show background backup total progress",
   "setting_pages_app_bar_settings": "Settings",
+  "setting_languages_title": "Languages",
   "settings_require_restart": "Please restart Immich to apply this setting",
+  "setting_languages_apply": "Apply",
   "share_add": "Add",
   "share_add_photos": "Add photos",
   "share_add_title": "Add a title",
diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist
index d2414c23ec..64b4ea5474 100644
--- a/mobile/ios/Runner/Info.plist
+++ b/mobile/ios/Runner/Info.plist
@@ -1,121 +1,124 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
-	<dict>
-		<key>BGTaskSchedulerPermittedIdentifiers</key>
-		<array>
-			<string>app.alextran.immich.backgroundFetch</string>
-			<string>app.alextran.immich.backgroundProcessing</string>
-		</array>
-		<key>CADisableMinimumFrameDurationOnPhone</key>
-		<true/>
-		<key>CFBundleDevelopmentRegion</key>
-		<string>$(DEVELOPMENT_LANGUAGE)</string>
-		<key>CFBundleDisplayName</key>
-		<string>Immich</string>
-		<key>CFBundleExecutable</key>
-		<string>$(EXECUTABLE_NAME)</string>
-		<key>CFBundleIdentifier</key>
-		<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-		<key>CFBundleInfoDictionaryVersion</key>
-		<string>6.0</string>
-		<key>CFBundleLocalizations</key>
-		<array>
-			<string>en</string>
-			<string>de</string>
-			<string>da</string>
-			<string>it</string>
-			<string>es</string>
-			<string>vi</string>
-			<string>fr</string>
-			<string>ja</string>
-			<string>pl</string>
-			<string>fi</string>
-			<string>pt</string>
-			<string>cs</string>
-			<string>uk</string>
-			<string>ru</string>
-			<string>zh</string>
-			<string>sk</string>
-			<string>nl</string>
-			<string>nb</string>
-			<string>sv</string>
-			<string>mn</string>
-			<string>ko</string>
-			<string>sr</string>
-			<string>hi</string>
-			<string>ca</string>
-			<string>hu</string>
-			<string>lv</string>
-			<string>th</string>
-			<string>sl</string>
-		</array>
-		<key>CFBundleName</key>
-		<string>immich_mobile</string>
-		<key>CFBundlePackageType</key>
-		<string>APPL</string>
-		<key>CFBundleShortVersionString</key>
-		<string>1.101.0</string>
-		<key>CFBundleSignature</key>
-		<string>????</string>
-		<key>CFBundleVersion</key>
-		<string>147</string>
-		<key>FLTEnableImpeller</key>
-		<true/>
-		<key>ITSAppUsesNonExemptEncryption</key>
-		<false/>
-		<key>LSApplicationQueriesSchemes</key>
-		<array>
-			<string>https</string>
-		</array>
-		<key>LSRequiresIPhoneOS</key>
-		<true/>
-		<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
-		<true/>
-		<key>NSAppTransportSecurity</key>
-		<dict>
-			<key>NSAllowsArbitraryLoads</key>
-			<true/>
-		</dict>
-		<key>NSCameraUsageDescription</key>
-		<string>We need to access the camera to let you take beautiful video using this app</string>
-		<key>NSLocationWhenInUseUsageDescription</key>
-		<string>Enable location setting to show position of assets on map</string>
-		<key>NSMicrophoneUsageDescription</key>
-		<string>We need to access the microphone to let you take beautiful video using this app</string>
-		<key>NSPhotoLibraryAddUsageDescription</key>
-		<string>We need to manage backup your photos album</string>
-		<key>NSPhotoLibraryUsageDescription</key>
-		<string>We need to manage backup your photos album</string>
-		<key>UIApplicationSupportsIndirectInputEvents</key>
-		<true/>
-		<key>UIBackgroundModes</key>
-		<array>
-			<string>fetch</string>
-			<string>processing</string>
-		</array>
-		<key>UILaunchStoryboardName</key>
-		<string>LaunchScreen</string>
-		<key>UIMainStoryboardFile</key>
-		<string>Main</string>
-		<key>UIStatusBarHidden</key>
-		<false/>
-		<key>UISupportedInterfaceOrientations</key>
-		<array>
-			<string>UIInterfaceOrientationPortrait</string>
-			<string>UIInterfaceOrientationLandscapeLeft</string>
-			<string>UIInterfaceOrientationLandscapeRight</string>
-		</array>
-		<key>UISupportedInterfaceOrientations~ipad</key>
-		<array>
-			<string>UIInterfaceOrientationPortrait</string>
-			<string>UIInterfaceOrientationPortraitUpsideDown</string>
-			<string>UIInterfaceOrientationLandscapeLeft</string>
-			<string>UIInterfaceOrientationLandscapeRight</string>
-		</array>
-		<key>UIViewControllerBasedStatusBarAppearance</key>
-		<true/>
-		<key>io.flutter.embedded_views_preview</key>
-		<true/>
-	</dict>
-</plist>
+  <dict>
+    <key>BGTaskSchedulerPermittedIdentifiers</key>
+    <array>
+      <string>app.alextran.immich.backgroundFetch</string>
+      <string>app.alextran.immich.backgroundProcessing</string>
+    </array>
+    <key>CADisableMinimumFrameDurationOnPhone</key>
+    <true />
+    <key>CFBundleDevelopmentRegion</key>
+    <string>$(DEVELOPMENT_LANGUAGE)</string>
+    <key>CFBundleDisplayName</key>
+    <string>Immich</string>
+    <key>CFBundleExecutable</key>
+    <string>$(EXECUTABLE_NAME)</string>
+    <key>CFBundleIdentifier</key>
+    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundleLocalizations</key>
+    <array>
+      <string>en</string>
+      <string>ar</string>
+      <string>ca</string>
+      <string>cs</string>
+      <string>da</string>
+      <string>de</string>
+      <string>es</string>
+      <string>fi</string>
+      <string>fr</string>
+      <string>he</string>
+      <string>hi</string>
+      <string>hu</string>
+      <string>it</string>
+      <string>ja</string>
+      <string>ko</string>
+      <string>lv</string>
+      <string>mn</string>
+      <string>nb</string>
+      <string>nl</string>
+      <string>pl</string>
+      <string>pt</string>
+      <string>ro</string>
+      <string>ru</string>
+      <string>sk</string>
+      <string>sl</string>
+      <string>sr</string>
+      <string>sv</string>
+      <string>th</string>
+      <string>uk</string>
+      <string>vi</string>
+      <string>zh</string>
+    </array>
+    <key>CFBundleName</key>
+    <string>immich_mobile</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleShortVersionString</key>
+    <string>1.101.0</string>
+    <key>CFBundleSignature</key>
+    <string>????</string>
+    <key>CFBundleVersion</key>
+    <string>147</string>
+    <key>FLTEnableImpeller</key>
+    <true />
+    <key>ITSAppUsesNonExemptEncryption</key>
+    <false />
+    <key>LSApplicationQueriesSchemes</key>
+    <array>
+      <string>https</string>
+    </array>
+    <key>LSRequiresIPhoneOS</key>
+    <true />
+    <key>MGLMapboxMetricsEnabledSettingShownInApp</key>
+    <true />
+    <key>NSAppTransportSecurity</key>
+    <dict>
+      <key>NSAllowsArbitraryLoads</key>
+      <true />
+    </dict>
+    <key>NSCameraUsageDescription</key>
+    <string>We need to access the camera to let you take beautiful video using this app</string>
+    <key>NSLocationWhenInUseUsageDescription</key>
+    <string>Enable location setting to show position of assets on map</string>
+    <key>NSMicrophoneUsageDescription</key>
+    <string>We need to access the microphone to let you take beautiful video using this app</string>
+    <key>NSPhotoLibraryAddUsageDescription</key>
+    <string>We need to manage backup your photos album</string>
+    <key>NSPhotoLibraryUsageDescription</key>
+    <string>We need to manage backup your photos album</string>
+    <key>UIApplicationSupportsIndirectInputEvents</key>
+    <true />
+    <key>UIBackgroundModes</key>
+    <array>
+      <string>fetch</string>
+      <string>processing</string>
+    </array>
+    <key>UILaunchStoryboardName</key>
+    <string>LaunchScreen</string>
+    <key>UIMainStoryboardFile</key>
+    <string>Main</string>
+    <key>UIStatusBarHidden</key>
+    <false />
+    <key>UISupportedInterfaceOrientations</key>
+    <array>
+      <string>UIInterfaceOrientationPortrait</string>
+      <string>UIInterfaceOrientationLandscapeLeft</string>
+      <string>UIInterfaceOrientationLandscapeRight</string>
+    </array>
+    <key>UISupportedInterfaceOrientations~ipad</key>
+    <array>
+      <string>UIInterfaceOrientationPortrait</string>
+      <string>UIInterfaceOrientationPortraitUpsideDown</string>
+      <string>UIInterfaceOrientationLandscapeLeft</string>
+      <string>UIInterfaceOrientationLandscapeRight</string>
+    </array>
+    <key>UIViewControllerBasedStatusBarAppearance</key>
+    <true />
+    <key>io.flutter.embedded_views_preview</key>
+    <true />
+  </dict>
+</plist>
\ No newline at end of file
diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart
index 18df612dc4..e697e41c07 100644
--- a/mobile/lib/constants/locales.dart
+++ b/mobile/lib/constants/locales.dart
@@ -1,43 +1,48 @@
 import 'dart:ui';
 
-const List<Locale> locales = [
+const Map<String, Locale> locales = {
   // Default locale
-  Locale('en', 'US'),
+  'English (en_US)': Locale('en', 'US'),
   // Additional locales
-  Locale('de', 'DE'),
-  Locale('da', 'DK'),
-  Locale('it', 'IT'),
-  Locale('es', 'ES'),
-  Locale('vi', 'VN'),
-  Locale('fr', 'CA'),
-  Locale('fr', 'FR'),
-  Locale('ja', 'JP'),
-  Locale('pl', 'PL'),
-  Locale('fi', 'FI'),
-  Locale('pt', 'PT'),
-  Locale('cs', 'CZ'),
-  Locale('uk', 'UA'),
-  Locale('ru', 'RU'),
-  Locale('zh', 'CN'),
-  Locale('sk', 'SK'),
-  Locale('nl', 'NL'),
-  Locale('nb', 'NO'),
-  Locale('sv', 'SE'),
-  Locale('mn', 'MN'),
-  Locale('ko', 'KR'),
-  Locale('sr', 'Latn'),
-  Locale('sr', 'Cyrl'),
-  Locale('hi', 'IN'),
-  Locale('es', 'PE'),
-  Locale('es', 'MX'),
-  Locale('es', 'US'),
-  Locale('sv', 'FI'),
-  Locale('ca', 'CA'),
-  Locale('hu', 'HU'),
-  Locale('lv', 'LV'),
-  Locale('zh', 'Hans'),
-  Locale('th', 'TH'),
-  Locale('sl', 'SI'),
-];
+  'Arabic (ar_JO)': Locale('ar', 'JO'),
+  'Catalan (ca_CA)': Locale('ca', 'CA'),
+  'Chinese (zh_CN)': Locale('zh', 'CN'),
+  'Chinese Simplified (zh_Hans)': Locale('zh', 'Hans'),
+  'Czech (cs_CZ)': Locale('cs', 'CZ'),
+  'Danish (da_DK)': Locale('da', 'DK'),
+  'Dutch (nl_NL)': Locale('nl', 'NL'),
+  'Finnish (fi_FI)': Locale('fi', 'FI'),
+  'French (fr_CA)': Locale('fr', 'CA'),
+  'French (fr_FR)': Locale('fr', 'FR'),
+  'German (de_DE)': Locale('de', 'DE'),
+  'Greek (el_GR)': Locale('el', 'GR'),
+  'Hebrew (he_IL)': Locale('he', 'IL'),
+  'Hindi (hi_IN)': Locale('hi', 'IN'),
+  'Hungarian (hu_HU)': Locale('hu', 'HU'),
+  'Italian (it_IT)': Locale('it', 'IT'),
+  'Japanese (ja_JP)': Locale('ja', 'JP'),
+  'Korean (ko_KR)': Locale('ko', 'KR'),
+  'Latvian (lv_LV)': Locale('lv', 'LV'),
+  'Lithuanian (lt_LT)': Locale('lt', 'LT'),
+  'Mongolian (mn_MN)': Locale('mn', 'MN'),
+  'Norwegian Bokmål (nb_NO)': Locale('nb', 'NO'),
+  'Polish (pl_PL)': Locale('pl', 'PL'),
+  'Portuguese (pt_PT)': Locale('pt', 'PT'),
+  'Romanian (ro_RO)': Locale('ro', 'RO'),
+  'Russian (ru_RU)': Locale('ru', 'RU'),
+  'Serbian Cyrillic (sr_Cyrl)': Locale('sr', 'Cyrl'),
+  'Serbian Latin (sr_Latn)': Locale('sr', 'Latn'),
+  'Slovak (sk_SK)': Locale('sk', 'SK'),
+  'Slovenian (sl_SI)': Locale('sl', 'SI'),
+  'Spanish (es_ES)': Locale('es', 'ES'),
+  'Spanish (es_MX)': Locale('es', 'MX'),
+  'Spanish (es_PE)': Locale('es', 'PE'),
+  'Spanish (es_US)': Locale('es', 'US'),
+  'Swedish (sv_FI)': Locale('sv', 'FI'),
+  'Swedish (sv_SE)': Locale('sv', 'SE'),
+  'Thai (th_TH)': Locale('th', 'TH'),
+  'Ukrainian (uk_UA)': Locale('uk', 'UA'),
+  'Vietnamese (vi_VN)': Locale('vi', 'VN'),
+};
 
 const String translationsPath = 'assets/i18n';
diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart
index f20cf7ecc6..48cac8f7d1 100644
--- a/mobile/lib/main.dart
+++ b/mobile/lib/main.dart
@@ -1,225 +1,225 @@
-import 'dart:async';
-import 'dart:io';
-
-import 'package:device_info_plus/device_info_plus.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_displaymode/flutter_displaymode.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/extensions/build_context_extensions.dart';
-import 'package:timezone/data/latest.dart';
-import 'package:immich_mobile/constants/locales.dart';
-import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
-import 'package:immich_mobile/modules/backup/models/backup_album.model.dart';
-import 'package:immich_mobile/modules/backup/models/duplicated_asset.model.dart';
-import 'package:immich_mobile/routing/router.dart';
-import 'package:immich_mobile/routing/tab_navigation_observer.dart';
-import 'package:immich_mobile/shared/cache/widgets_binding.dart';
-import 'package:immich_mobile/shared/models/album.dart';
-import 'package:immich_mobile/shared/models/android_device_asset.dart';
-import 'package:immich_mobile/shared/models/asset.dart';
-import 'package:immich_mobile/shared/models/etag.dart';
-import 'package:immich_mobile/shared/models/exif_info.dart';
-import 'package:immich_mobile/shared/models/ios_device_asset.dart';
-import 'package:immich_mobile/shared/models/logger_message.model.dart';
-import 'package:immich_mobile/shared/models/store.dart';
-import 'package:immich_mobile/shared/models/user.dart';
-import 'package:immich_mobile/shared/providers/app_state.provider.dart';
-import 'package:immich_mobile/shared/providers/db.provider.dart';
-import 'package:immich_mobile/shared/services/immich_logger.service.dart';
-import 'package:immich_mobile/shared/services/local_notification.service.dart';
-import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
-import 'package:immich_mobile/utils/immich_app_theme.dart';
-import 'package:immich_mobile/utils/migration.dart';
-import 'package:isar/isar.dart';
-import 'package:logging/logging.dart';
-import 'package:path_provider/path_provider.dart';
-
-void main() async {
-  ImmichWidgetsBinding();
-
-  final db = await loadDb();
-  await initApp();
-  await migrateDatabaseIfNeeded(db);
-  HttpOverrides.global = HttpSSLCertOverride();
-
-  runApp(
-    ProviderScope(
-      overrides: [dbProvider.overrideWithValue(db)],
-      child: const MainWidget(),
-    ),
-  );
-}
-
-Future<void> initApp() async {
-  await EasyLocalization.ensureInitialized();
-
-  if (kReleaseMode && Platform.isAndroid) {
-    try {
-      await FlutterDisplayMode.setHighRefreshRate();
-      debugPrint("Enabled high refresh mode");
-    } catch (e) {
-      debugPrint("Error setting high refresh rate: $e");
-    }
-  }
-
-  // Initialize Immich Logger Service
-  ImmichLogger();
-
-  var log = Logger("ImmichErrorLogger");
-
-  FlutterError.onError = (details) {
-    FlutterError.presentError(details);
-    log.severe(
-      'FlutterError - Catch all',
-      "${details.toString()}\nException: ${details.exception}\nLibrary: ${details.library}\nContext: ${details.context}",
-      details.stack,
-    );
-  };
-
-  PlatformDispatcher.instance.onError = (error, stack) {
-    log.severe('PlatformDispatcher - Catch all', error, stack);
-    return true;
-  };
-
-  initializeTimeZones();
-}
-
-Future<Isar> loadDb() async {
-  final dir = await getApplicationDocumentsDirectory();
-  Isar db = await Isar.open(
-    [
-      StoreValueSchema,
-      ExifInfoSchema,
-      AssetSchema,
-      AlbumSchema,
-      UserSchema,
-      BackupAlbumSchema,
-      DuplicatedAssetSchema,
-      LoggerMessageSchema,
-      ETagSchema,
-      if (Platform.isAndroid) AndroidDeviceAssetSchema,
-      if (Platform.isIOS) IOSDeviceAssetSchema,
-    ],
-    directory: dir.path,
-    maxSizeMiB: 256,
-  );
-  Store.init(db);
-  return db;
-}
-
-class ImmichApp extends ConsumerStatefulWidget {
-  const ImmichApp({super.key});
-
-  @override
-  ImmichAppState createState() => ImmichAppState();
-}
-
-class ImmichAppState extends ConsumerState<ImmichApp>
-    with WidgetsBindingObserver {
-  @override
-  void didChangeAppLifecycleState(AppLifecycleState state) {
-    switch (state) {
-      case AppLifecycleState.resumed:
-        debugPrint("[APP STATE] resumed");
-        ref.read(appStateProvider.notifier).handleAppResume();
-        break;
-      case AppLifecycleState.inactive:
-        debugPrint("[APP STATE] inactive");
-        ref.read(appStateProvider.notifier).handleAppInactivity();
-        break;
-      case AppLifecycleState.paused:
-        debugPrint("[APP STATE] paused");
-        ref.read(appStateProvider.notifier).handleAppPause();
-        break;
-      case AppLifecycleState.detached:
-        debugPrint("[APP STATE] detached");
-        ref.read(appStateProvider.notifier).handleAppDetached();
-        break;
-      case AppLifecycleState.hidden:
-        debugPrint("[APP STATE] hidden");
-        ref.read(appStateProvider.notifier).handleAppHidden();
-        break;
-    }
-  }
-
-  Future<void> initApp() async {
-    WidgetsBinding.instance.addObserver(this);
-
-    // Draw the app from edge to edge
-    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
-
-    // Sets the navigation bar color
-    SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(
-      systemNavigationBarColor: Colors.transparent,
-    );
-    if (Platform.isAndroid) {
-      // Android 8 does not support transparent app bars
-      final info = await DeviceInfoPlugin().androidInfo;
-      if (info.version.sdkInt <= 26) {
-        overlayStyle = context.isDarkTheme
-            ? SystemUiOverlayStyle.dark
-            : SystemUiOverlayStyle.light;
-      }
-    }
-    SystemChrome.setSystemUIOverlayStyle(overlayStyle);
-    await ref.read(localNotificationService).setup();
-  }
-
-  @override
-  initState() {
-    super.initState();
-    initApp().then((_) => debugPrint("App Init Completed"));
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      // needs to be delayed so that EasyLocalization is working
-      ref.read(backgroundServiceProvider).resumeServiceIfEnabled();
-    });
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    var router = ref.watch(appRouterProvider);
-
-    return MaterialApp(
-      localizationsDelegates: context.localizationDelegates,
-      supportedLocales: context.supportedLocales,
-      locale: context.locale,
-      debugShowCheckedModeBanner: false,
-      home: MaterialApp.router(
-        title: 'Immich',
-        debugShowCheckedModeBanner: false,
-        themeMode: ref.watch(immichThemeProvider),
-        darkTheme: immichDarkTheme,
-        theme: immichLightTheme,
-        routeInformationParser: router.defaultRouteParser(),
-        routerDelegate: router.delegate(
-          navigatorObservers: () => [TabNavigationObserver(ref: ref)],
-        ),
-      ),
-    );
-  }
-}
-
-// ignore: prefer-single-widget-per-file
-class MainWidget extends StatelessWidget {
-  const MainWidget({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return EasyLocalization(
-      supportedLocales: locales,
-      path: translationsPath,
-      useFallbackTranslations: true,
-      fallbackLocale: locales.first,
-      child: const ImmichApp(),
-    );
-  }
-}
+import 'dart:async';
+import 'dart:io';
+
+import 'package:device_info_plus/device_info_plus.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_displaymode/flutter_displaymode.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/extensions/build_context_extensions.dart';
+import 'package:timezone/data/latest.dart';
+import 'package:immich_mobile/constants/locales.dart';
+import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
+import 'package:immich_mobile/modules/backup/models/backup_album.model.dart';
+import 'package:immich_mobile/modules/backup/models/duplicated_asset.model.dart';
+import 'package:immich_mobile/routing/router.dart';
+import 'package:immich_mobile/routing/tab_navigation_observer.dart';
+import 'package:immich_mobile/shared/cache/widgets_binding.dart';
+import 'package:immich_mobile/shared/models/album.dart';
+import 'package:immich_mobile/shared/models/android_device_asset.dart';
+import 'package:immich_mobile/shared/models/asset.dart';
+import 'package:immich_mobile/shared/models/etag.dart';
+import 'package:immich_mobile/shared/models/exif_info.dart';
+import 'package:immich_mobile/shared/models/ios_device_asset.dart';
+import 'package:immich_mobile/shared/models/logger_message.model.dart';
+import 'package:immich_mobile/shared/models/store.dart';
+import 'package:immich_mobile/shared/models/user.dart';
+import 'package:immich_mobile/shared/providers/app_state.provider.dart';
+import 'package:immich_mobile/shared/providers/db.provider.dart';
+import 'package:immich_mobile/shared/services/immich_logger.service.dart';
+import 'package:immich_mobile/shared/services/local_notification.service.dart';
+import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
+import 'package:immich_mobile/utils/immich_app_theme.dart';
+import 'package:immich_mobile/utils/migration.dart';
+import 'package:isar/isar.dart';
+import 'package:logging/logging.dart';
+import 'package:path_provider/path_provider.dart';
+
+void main() async {
+  ImmichWidgetsBinding();
+
+  final db = await loadDb();
+  await initApp();
+  await migrateDatabaseIfNeeded(db);
+  HttpOverrides.global = HttpSSLCertOverride();
+
+  runApp(
+    ProviderScope(
+      overrides: [dbProvider.overrideWithValue(db)],
+      child: const MainWidget(),
+    ),
+  );
+}
+
+Future<void> initApp() async {
+  await EasyLocalization.ensureInitialized();
+
+  if (kReleaseMode && Platform.isAndroid) {
+    try {
+      await FlutterDisplayMode.setHighRefreshRate();
+      debugPrint("Enabled high refresh mode");
+    } catch (e) {
+      debugPrint("Error setting high refresh rate: $e");
+    }
+  }
+
+  // Initialize Immich Logger Service
+  ImmichLogger();
+
+  var log = Logger("ImmichErrorLogger");
+
+  FlutterError.onError = (details) {
+    FlutterError.presentError(details);
+    log.severe(
+      'FlutterError - Catch all',
+      "${details.toString()}\nException: ${details.exception}\nLibrary: ${details.library}\nContext: ${details.context}",
+      details.stack,
+    );
+  };
+
+  PlatformDispatcher.instance.onError = (error, stack) {
+    log.severe('PlatformDispatcher - Catch all', error, stack);
+    return true;
+  };
+
+  initializeTimeZones();
+}
+
+Future<Isar> loadDb() async {
+  final dir = await getApplicationDocumentsDirectory();
+  Isar db = await Isar.open(
+    [
+      StoreValueSchema,
+      ExifInfoSchema,
+      AssetSchema,
+      AlbumSchema,
+      UserSchema,
+      BackupAlbumSchema,
+      DuplicatedAssetSchema,
+      LoggerMessageSchema,
+      ETagSchema,
+      if (Platform.isAndroid) AndroidDeviceAssetSchema,
+      if (Platform.isIOS) IOSDeviceAssetSchema,
+    ],
+    directory: dir.path,
+    maxSizeMiB: 256,
+  );
+  Store.init(db);
+  return db;
+}
+
+class ImmichApp extends ConsumerStatefulWidget {
+  const ImmichApp({super.key});
+
+  @override
+  ImmichAppState createState() => ImmichAppState();
+}
+
+class ImmichAppState extends ConsumerState<ImmichApp>
+    with WidgetsBindingObserver {
+  @override
+  void didChangeAppLifecycleState(AppLifecycleState state) {
+    switch (state) {
+      case AppLifecycleState.resumed:
+        debugPrint("[APP STATE] resumed");
+        ref.read(appStateProvider.notifier).handleAppResume();
+        break;
+      case AppLifecycleState.inactive:
+        debugPrint("[APP STATE] inactive");
+        ref.read(appStateProvider.notifier).handleAppInactivity();
+        break;
+      case AppLifecycleState.paused:
+        debugPrint("[APP STATE] paused");
+        ref.read(appStateProvider.notifier).handleAppPause();
+        break;
+      case AppLifecycleState.detached:
+        debugPrint("[APP STATE] detached");
+        ref.read(appStateProvider.notifier).handleAppDetached();
+        break;
+      case AppLifecycleState.hidden:
+        debugPrint("[APP STATE] hidden");
+        ref.read(appStateProvider.notifier).handleAppHidden();
+        break;
+    }
+  }
+
+  Future<void> initApp() async {
+    WidgetsBinding.instance.addObserver(this);
+
+    // Draw the app from edge to edge
+    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
+
+    // Sets the navigation bar color
+    SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(
+      systemNavigationBarColor: Colors.transparent,
+    );
+    if (Platform.isAndroid) {
+      // Android 8 does not support transparent app bars
+      final info = await DeviceInfoPlugin().androidInfo;
+      if (info.version.sdkInt <= 26) {
+        overlayStyle = context.isDarkTheme
+            ? SystemUiOverlayStyle.dark
+            : SystemUiOverlayStyle.light;
+      }
+    }
+    SystemChrome.setSystemUIOverlayStyle(overlayStyle);
+    await ref.read(localNotificationService).setup();
+  }
+
+  @override
+  initState() {
+    super.initState();
+    initApp().then((_) => debugPrint("App Init Completed"));
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      // needs to be delayed so that EasyLocalization is working
+      ref.read(backgroundServiceProvider).resumeServiceIfEnabled();
+    });
+  }
+
+  @override
+  void dispose() {
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    var router = ref.watch(appRouterProvider);
+
+    return MaterialApp(
+      localizationsDelegates: context.localizationDelegates,
+      supportedLocales: context.supportedLocales,
+      locale: context.locale,
+      debugShowCheckedModeBanner: false,
+      home: MaterialApp.router(
+        title: 'Immich',
+        debugShowCheckedModeBanner: false,
+        themeMode: ref.watch(immichThemeProvider),
+        darkTheme: immichDarkTheme,
+        theme: immichLightTheme,
+        routeInformationParser: router.defaultRouteParser(),
+        routerDelegate: router.delegate(
+          navigatorObservers: () => [TabNavigationObserver(ref: ref)],
+        ),
+      ),
+    );
+  }
+}
+
+// ignore: prefer-single-widget-per-file
+class MainWidget extends StatelessWidget {
+  const MainWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return EasyLocalization(
+      supportedLocales: locales.values.toList(),
+      path: translationsPath,
+      useFallbackTranslations: true,
+      fallbackLocale: locales.values.first,
+      child: const ImmichApp(),
+    );
+  }
+}
diff --git a/mobile/lib/modules/backup/background_service/localization.dart b/mobile/lib/modules/backup/background_service/localization.dart
index a0c1610ece..c8ef662896 100644
--- a/mobile/lib/modules/backup/background_service/localization.dart
+++ b/mobile/lib/modules/backup/background_service/localization.dart
@@ -1,31 +1,31 @@
-// ignore_for_file: implementation_imports
-
-import 'package:flutter/foundation.dart';
-import 'package:easy_localization/src/asset_loader.dart';
-import 'package:easy_localization/src/easy_localization_controller.dart';
-import 'package:easy_localization/src/localization.dart';
-import 'package:immich_mobile/constants/locales.dart';
-
-/// Workaround to manually load translations in another Isolate
-Future<bool> loadTranslations() async {
-  await EasyLocalizationController.initEasyLocation();
-
-  final controller = EasyLocalizationController(
-    supportedLocales: locales,
-    useFallbackTranslations: true,
-    saveLocale: true,
-    assetLoader: const RootBundleAssetLoader(),
-    path: translationsPath,
-    useOnlyLangCode: false,
-    onLoadError: (e) => debugPrint(e.toString()),
-    fallbackLocale: locales.first,
-  );
-
-  await controller.loadTranslations();
-
-  return Localization.load(
-    controller.locale,
-    translations: controller.translations,
-    fallbackTranslations: controller.fallbackTranslations,
-  );
-}
+// ignore_for_file: implementation_imports
+
+import 'package:flutter/foundation.dart';
+import 'package:easy_localization/src/asset_loader.dart';
+import 'package:easy_localization/src/easy_localization_controller.dart';
+import 'package:easy_localization/src/localization.dart';
+import 'package:immich_mobile/constants/locales.dart';
+
+/// Workaround to manually load translations in another Isolate
+Future<bool> loadTranslations() async {
+  await EasyLocalizationController.initEasyLocation();
+
+  final controller = EasyLocalizationController(
+    supportedLocales: locales.values.toList(),
+    useFallbackTranslations: true,
+    saveLocale: true,
+    assetLoader: const RootBundleAssetLoader(),
+    path: translationsPath,
+    useOnlyLangCode: false,
+    onLoadError: (e) => debugPrint(e.toString()),
+    fallbackLocale: locales.values.first,
+  );
+
+  await controller.loadTranslations();
+
+  return Localization.load(
+    controller.locale,
+    translations: controller.translations,
+    fallbackTranslations: controller.fallbackTranslations,
+  );
+}
diff --git a/mobile/lib/modules/settings/views/settings_page.dart b/mobile/lib/modules/settings/views/settings_page.dart
index eeb4b379f2..bfe8899924 100644
--- a/mobile/lib/modules/settings/views/settings_page.dart
+++ b/mobile/lib/modules/settings/views/settings_page.dart
@@ -2,7 +2,10 @@ import 'package:auto_route/auto_route.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/constants/locales.dart';
 import 'package:immich_mobile/extensions/build_context_extensions.dart';
+import 'package:immich_mobile/modules/backup/background_service/localization.dart';
 import 'package:immich_mobile/modules/settings/ui/advanced_settings.dart';
 import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_settings.dart';
 import 'package:immich_mobile/modules/settings/ui/backup_settings/backup_settings.dart';
@@ -16,6 +19,7 @@ enum SettingSection {
     'setting_notifications_title',
     Icons.notifications_none_rounded,
   ),
+  languages('setting_languages_title', Icons.language),
   preferences('preferences_settings_title', Icons.interests_outlined),
   backup('backup_controller_page_backup', Icons.cloud_upload_outlined),
   timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined),
@@ -27,6 +31,7 @@ enum SettingSection {
 
   Widget get widget => switch (this) {
         SettingSection.notifications => const NotificationSetting(),
+        SettingSection.languages => const LanguageSettings(),
         SettingSection.preferences => const PreferenceSetting(),
         SettingSection.backup => const BackupSettings(),
         SettingSection.timeline => const AssetListSettings(),
@@ -37,6 +42,70 @@ enum SettingSection {
   const SettingSection(this.title, this.icon);
 }
 
+class LanguageSettings extends HookConsumerWidget {
+  const LanguageSettings({super.key});
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final currentLocale = context.locale;
+    final textController = useTextEditingController(
+      text: locales.keys.firstWhere(
+        (countryName) => locales[countryName] == currentLocale,
+      ),
+    );
+
+    final selectedLocale = useState<Locale>(currentLocale);
+
+    return ListView(
+      padding: const EdgeInsets.all(16),
+      children: [
+        DropdownMenu(
+          inputDecorationTheme: InputDecorationTheme(
+            border: OutlineInputBorder(
+              borderRadius: BorderRadius.circular(20),
+            ),
+            contentPadding: const EdgeInsets.only(left: 16),
+          ),
+          menuStyle: MenuStyle(
+            shape: MaterialStatePropertyAll<OutlinedBorder>(
+              RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(15),
+              ),
+            ),
+          ),
+          menuHeight: context.height * 0.5,
+          hintText: "Languages",
+          label: const Text('Languages'),
+          dropdownMenuEntries: locales.keys
+              .map(
+                (countryName) => DropdownMenuEntry(
+                  value: locales[countryName],
+                  label: countryName,
+                ),
+              )
+              .toList(),
+          controller: textController,
+          onSelected: (value) {
+            if (value != null) {
+              selectedLocale.value = value;
+            }
+          },
+        ),
+        const SizedBox(height: 16),
+        ElevatedButton(
+          onPressed: selectedLocale.value == currentLocale
+              ? null
+              : () {
+                  context.setLocale(selectedLocale.value);
+                  loadTranslations();
+                },
+          child: const Text('setting_languages_apply').tr(),
+        ),
+      ],
+    );
+  }
+}
+
 @RoutePage()
 class SettingsPage extends StatelessWidget {
   const SettingsPage({super.key});