diff --git a/packages/ui/src/App.tsx b/packages/ui/src/App.tsx
index 1d753db77..2cc8a8b57 100644
--- a/packages/ui/src/App.tsx
+++ b/packages/ui/src/App.tsx
@@ -15,8 +15,6 @@ import getSignInExperienceSettings from './utils/sign-in-experience';
 
 import './scss/normalized.scss';
 
-void initI18n();
-
 const App = () => {
   const [loading, setLoading] = useState(false);
   const [toast, setToast] = useState('');
@@ -30,9 +28,13 @@ const App = () => {
   useEffect(() => {
     (async () => {
       setLoading(true);
-      // TODO: error handling
-      const { settings } = await getSignInExperienceSettings();
+      const settings = await getSignInExperienceSettings();
+
+      // Note: i18n must be initialized ahead of global experience settings
+      await initI18n(settings.languageInfo);
+
       setExperienceSettings(settings);
+
       setLoading(false);
     })();
   }, []);
diff --git a/packages/ui/src/components/Input/index.module.scss b/packages/ui/src/components/Input/index.module.scss
index cfbb3e98c..8972dc9a4 100644
--- a/packages/ui/src/components/Input/index.module.scss
+++ b/packages/ui/src/components/Input/index.module.scss
@@ -29,6 +29,7 @@
     padding: _.unit(3) 0;
     caret-color: var(--color-primary);
     font: var(--font-body-bold);
+    color: var(--color-text);
 
     &::placeholder {
       color: var(--color-caption);
diff --git a/packages/ui/src/i18n/init.ts b/packages/ui/src/i18n/init.ts
index 142bc4129..54a87aa34 100644
--- a/packages/ui/src/i18n/init.ts
+++ b/packages/ui/src/i18n/init.ts
@@ -1,18 +1,24 @@
 import resources from '@logto/phrases';
-import i18next from 'i18next';
+import { LanguageInfo } from '@logto/schemas';
+import i18next, { InitOptions } from 'i18next';
 import LanguageDetector from 'i18next-browser-languagedetector';
 import { initReactI18next } from 'react-i18next';
 
-const initI18n = async () =>
-  i18next
-    .use(initReactI18next)
-    .use(LanguageDetector)
-    .init({
-      resources,
-      fallbackLng: 'en',
-      interpolation: {
-        escapeValue: false,
-      },
-    });
+const initI18n = async (languageSettings?: LanguageInfo) => {
+  const baseOptions: InitOptions = {
+    resources,
+    fallbackLng: languageSettings?.fallbackLanguage ?? 'en',
+    interpolation: {
+      escapeValue: false,
+    },
+  };
+
+  const options: InitOptions =
+    languageSettings?.autoDetect === false
+      ? { ...baseOptions, lng: languageSettings.fixedLanguage }
+      : baseOptions;
+
+  return i18next.use(initReactI18next).use(LanguageDetector).init(options);
+};
 
 export default initI18n;
diff --git a/packages/ui/src/utils/sign-in-experience.test.ts b/packages/ui/src/utils/sign-in-experience.test.ts
index 94ebecce7..0d0b6d389 100644
--- a/packages/ui/src/utils/sign-in-experience.test.ts
+++ b/packages/ui/src/utils/sign-in-experience.test.ts
@@ -12,14 +12,14 @@ describe('getSignInExperienceSettings', () => {
 
   it('should return the sign in experience settings', async () => {
     getSignInExperienceMock.mockResolvedValueOnce(mockSignInExperience);
-    const { settings } = await getSignInExperienceSettings();
+    const settings = await getSignInExperienceSettings();
 
-    expect(settings?.branding).toEqual(mockSignInExperience.branding);
-    expect(settings?.languageInfo).toEqual(mockSignInExperience.languageInfo);
-    expect(settings?.termsOfUse).toEqual(mockSignInExperience.termsOfUse);
-    expect(settings?.primarySignInMethod).toEqual('username');
-    expect(settings?.secondarySignInMethods).toContain('email');
-    expect(settings?.secondarySignInMethods).toContain('sms');
-    expect(settings?.secondarySignInMethods).toContain('social');
+    expect(settings.branding).toEqual(mockSignInExperience.branding);
+    expect(settings.languageInfo).toEqual(mockSignInExperience.languageInfo);
+    expect(settings.termsOfUse).toEqual(mockSignInExperience.termsOfUse);
+    expect(settings.primarySignInMethod).toEqual('username');
+    expect(settings.secondarySignInMethods).toContain('email');
+    expect(settings.secondarySignInMethods).toContain('sms');
+    expect(settings.secondarySignInMethods).toContain('social');
   });
 });
diff --git a/packages/ui/src/utils/sign-in-experience.ts b/packages/ui/src/utils/sign-in-experience.ts
index 9a5321eaf..2e7f3f76a 100644
--- a/packages/ui/src/utils/sign-in-experience.ts
+++ b/packages/ui/src/utils/sign-in-experience.ts
@@ -6,7 +6,7 @@
 import { SignInMethods } from '@logto/schemas';
 
 import { getSignInExperience } from '@/apis/settings';
-import { SignInMethod } from '@/types';
+import { SignInMethod, SignInExperienceSettings } from '@/types';
 
 const getPrimarySignInMethod = (signInMethods: SignInMethods) => {
   for (const [key, value] of Object.entries(signInMethods)) {
@@ -18,7 +18,7 @@ const getPrimarySignInMethod = (signInMethods: SignInMethods) => {
   return 'username';
 };
 
-const getSecondarySignInMethod = (signInMethods: SignInMethods) =>
+const getSecondarySignInMethods = (signInMethods: SignInMethods) =>
   Object.entries(signInMethods).reduce<SignInMethod[]>((methods, [key, value]) => {
     if (value === 'secondary') {
       return [...methods, key as SignInMethod];
@@ -27,21 +27,16 @@ const getSecondarySignInMethod = (signInMethods: SignInMethods) =>
     return methods;
   }, []);
 
-const getSignInExperienceSettings = async () => {
-  try {
-    const result = await getSignInExperience();
-    const settings = {
-      branding: result.branding,
-      languageInfo: result.languageInfo,
-      termsOfUse: result.termsOfUse,
-      primarySignInMethod: getPrimarySignInMethod(result.signInMethods),
-      secondarySignInMethods: getSecondarySignInMethod(result.signInMethods),
-    };
+const getSignInExperienceSettings = async (): Promise<SignInExperienceSettings> => {
+  const { branding, languageInfo, termsOfUse, signInMethods } = await getSignInExperience();
 
-    return { settings };
-  } catch (error: unknown) {
-    return { error };
-  }
+  return {
+    branding,
+    languageInfo,
+    termsOfUse,
+    primarySignInMethod: getPrimarySignInMethod(signInMethods),
+    secondarySignInMethods: getSecondarySignInMethods(signInMethods),
+  };
 };
 
 export default getSignInExperienceSettings;