Compare commits

...

3 Commits

Author SHA1 Message Date
Samuel Newman b1389cdf27 add android keyboard language change detection
uses ContentObserver on Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE
to detect when the user switches keyboard language on Android.
deduplicates events like the iOS side.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-01 10:15:28 +02:00
Samuel Newman e8793e49c8 add keyboard icon 2026-02-28 16:28:22 +02:00
Samuel Newman d1666345ae auto-detect composer language from keyboard
adds a new expo-keyboard-language native module that reads the current
keyboard language on iOS (via first responder's textInputMode) and
Android (via InputMethodManager). iOS also gets real-time updates when
the keyboard language changes.

users opt in via Settings > Languages > "Automatically detect post
language from keyboard" (native only, marked experimental). when
enabled, the composer language tracks the keyboard language. users can
override per-session by selecting a language manually, and re-enable
auto mode via the "Automatic" item in the language menu.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-28 16:00:45 +02:00
17 changed files with 451 additions and 40 deletions
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M18 2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7v2h15a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h3V5a1 1 0 0 1 1-1h11V3a1 1 0 0 1 1-1ZM3 20h18V10H3v10Zm3-4.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Zm12 0a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5ZM14 16a1 1 0 1 1 0 2h-4a1 1 0 1 1 0-2h4Zm-8.268 1.42h0Zm-.073-.057h0Zm-.06-.067h0Zm-.047-.078h0Zm-.033-.09q.006.027.016.055-.01-.027-.016-.055ZM5.5 17h0Zm.5-5.25a1.25 1.25 0 1 1-1.243 1.378L4.75 13l.007-.128A1.25 1.25 0 0 1 6 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L8.75 13l.007-.128A1.25 1.25 0 0 1 10 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L12.75 13l.007-.128A1.25 1.25 0 0 1 14 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L16.75 13l.007-.128A1.25 1.25 0 0 1 18 11.75ZM5.732 13.42h0Zm-.073-.057h0Zm-.06-.067h0Zm-.047-.078h0Zm-.033-.09q.006.028.016.055-.01-.028-.016-.055ZM5.5 13h0Z"/></svg>

After

Width:  |  Height:  |  Size: 940 B

@@ -0,0 +1,39 @@
apply plugin: 'com.android.library'
group = 'expo.modules.keyboardlanguage'
version = '1.0.0'
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
apply from: expoModulesCorePlugin
applyKotlinExpoModulesCorePlugin()
useCoreDependencies()
useExpoPublishing()
def useManagedAndroidSdkVersions = false
if (useManagedAndroidSdkVersions) {
useDefaultAndroidSdkVersions()
} else {
buildscript {
ext.safeExtGet = { prop, fallback ->
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
}
project.android {
compileSdkVersion safeExtGet("compileSdkVersion", 34)
defaultConfig {
minSdkVersion safeExtGet("minSdkVersion", 21)
targetSdkVersion safeExtGet("targetSdkVersion", 34)
}
}
}
android {
namespace "expo.modules.keyboardlanguage"
defaultConfig {
versionCode 1
versionName "1.0.0"
}
lintOptions {
abortOnError false
}
}
@@ -0,0 +1,68 @@
package expo.modules.keyboardlanguage
import android.database.ContentObserver
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.inputmethod.InputMethodManager
import androidx.core.content.getSystemService
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class ExpoKeyboardLanguageModule : Module() {
private var subtypeObserver: ContentObserver? = null
private var lastLanguage: String? = null
override fun definition() =
ModuleDefinition {
Name("ExpoKeyboardLanguage")
Events("onKeyboardLanguageChange")
Function("getCurrentKeyboardLanguage") {
return@Function getCurrentLanguage()
}
OnStartObserving {
val context = appContext.reactContext ?: return@OnStartObserving
val uri = Settings.Secure.getUriFor("selected_input_method_subtype")
subtypeObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean) {
val language = getCurrentLanguage()
if (language != lastLanguage) {
lastLanguage = language
sendEvent("onKeyboardLanguageChange", mapOf("language" to language))
}
}
}
context.contentResolver.registerContentObserver(uri, false, subtypeObserver!!)
}
OnStopObserving {
subtypeObserver?.let { observer ->
appContext.reactContext?.contentResolver?.unregisterContentObserver(observer)
}
subtypeObserver = null
}
}
private fun getCurrentLanguage(): String? {
val context = appContext.reactContext ?: return null
val imm = context.getSystemService<InputMethodManager>() ?: return null
val subtype = imm.currentInputMethodSubtype ?: return null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val tag = subtype.languageTag
if (tag.isNotEmpty()) return tag
}
@Suppress("DEPRECATION")
val locale = subtype.locale
if (locale.isNotEmpty()) return locale
return null
}
}
@@ -0,0 +1,9 @@
{
"platforms": ["ios", "android"],
"ios": {
"modules": ["ExpoKeyboardLanguageModule"]
},
"android": {
"modules": ["expo.modules.keyboardlanguage.ExpoKeyboardLanguageModule"]
}
}
+4
View File
@@ -0,0 +1,4 @@
export {
addKeyboardLanguageListener,
getCurrentKeyboardLanguage,
} from './src/index'
@@ -0,0 +1,20 @@
Pod::Spec.new do |s|
s.name = 'ExpoKeyboardLanguage'
s.version = '1.0.0'
s.summary = 'Expo module to detect the current keyboard language'
s.description = 'Expo module to detect the current keyboard language'
s.author = ''
s.homepage = 'https://github.com/bluesky-social/social-app'
s.platforms = { :ios => '13.4' }
s.source = { git: '' }
s.static_framework = true
s.dependency 'ExpoModulesCore'
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'SWIFT_COMPILATION_MODE' => 'wholemodule'
}
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
end
@@ -0,0 +1,75 @@
import ExpoModulesCore
public class ExpoKeyboardLanguageModule: Module {
public func definition() -> ModuleDefinition {
Name("ExpoKeyboardLanguage")
Events("onKeyboardLanguageChange")
Function("getCurrentKeyboardLanguage") {
return self.currentKeyboardLanguage()
}
OnStartObserving {
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onInputModeOrResponderChange),
name: UITextInputMode.currentInputModeDidChangeNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onInputModeOrResponderChange),
name: UIResponder.keyboardDidShowNotification,
object: nil
)
}
OnStopObserving {
NotificationCenter.default.removeObserver(
self,
name: UITextInputMode.currentInputModeDidChangeNotification,
object: nil
)
NotificationCenter.default.removeObserver(
self,
name: UIResponder.keyboardDidShowNotification,
object: nil
)
}
}
private var lastLanguage: String?
@objc
private func onInputModeOrResponderChange() {
let language = currentKeyboardLanguage()
if language != lastLanguage {
lastLanguage = language
sendEvent("onKeyboardLanguageChange", [
"language": language as Any
])
}
}
private func currentKeyboardLanguage() -> String? {
let keyWindow = UIApplication.shared.connectedScenes
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first { $0.isKeyWindow }
return keyWindow?.findFirstResponder()?.textInputMode?.primaryLanguage
}
}
private extension UIView {
func findFirstResponder() -> UIView? {
if isFirstResponder { return self }
for subview in subviews {
if let found = subview.findFirstResponder() {
return found
}
}
return nil
}
}
@@ -0,0 +1,26 @@
import {type EventSubscription} from 'expo-modules-core'
import {requireNativeModule} from 'expo-modules-core'
type ExpoKeyboardLanguageModule = {
getCurrentKeyboardLanguage(): string | null
addListener(
eventName: 'onKeyboardLanguageChange',
listener: (event: {language: string | null}) => void,
): EventSubscription
}
const NativeModule = requireNativeModule<ExpoKeyboardLanguageModule>(
'ExpoKeyboardLanguage',
)
export function getCurrentKeyboardLanguage(): string | null {
return NativeModule.getCurrentKeyboardLanguage()
}
export function addKeyboardLanguageListener(
cb: (language: string | null) => void,
): EventSubscription {
return NativeModule.addListener('onKeyboardLanguageChange', event => {
cb(event.language)
})
}
@@ -0,0 +1,11 @@
import {type EventSubscription} from 'expo-modules-core'
export function getCurrentKeyboardLanguage(): string | null {
return null
}
export function addKeyboardLanguageListener(
_cb: (language: string | null) => void,
): EventSubscription {
return {remove() {}}
}
+5
View File
@@ -0,0 +1,5 @@
import {createSinglePathSVG} from './TEMPLATE'
export const Keyboard_Stroke2_Corner0_Rounded = createSinglePathSVG({
path: 'M18 2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7v2h15a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h3V5a1 1 0 0 1 1-1h11V3a1 1 0 0 1 1-1ZM3 20h18V10H3v10Zm3-4.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Zm12 0a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5ZM14 16a1 1 0 1 1 0 2h-4a1 1 0 1 1 0-2h4Zm-8.268 1.42h0Zm-.073-.057h0Zm-.06-.067h0Zm-.047-.078h0Zm-.033-.09q.006.027.016.055-.01-.027-.016-.055ZM5.5 17h0Zm.5-5.25a1.25 1.25 0 1 1-1.243 1.378L4.75 13l.007-.128A1.25 1.25 0 0 1 6 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L8.75 13l.007-.128A1.25 1.25 0 0 1 10 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L12.75 13l.007-.128A1.25 1.25 0 0 1 14 11.75Zm4 0a1.25 1.25 0 1 1-1.243 1.378L16.75 13l.007-.128A1.25 1.25 0 0 1 18 11.75ZM5.732 13.42h0Zm-.073-.057h0Zm-.06-.067h0Zm-.047-.078h0Zm-.033-.09q.006.028.016.055-.01-.028-.016-.055ZM5.5 13h0Z',
})
+30
View File
@@ -0,0 +1,30 @@
import {useEffect, useState} from 'react'
import {
addKeyboardLanguageListener,
getCurrentKeyboardLanguage,
} from '../../../modules/expo-keyboard-language'
function toBcp2(tag: string | null): string | null {
if (!tag) return null
return tag.split('-')[0].toLowerCase()
}
/**
* Returns the current keyboard language as a 2-letter code (e.g. "en"),
* updating in real-time on iOS.
*/
export function useKeyboardLanguage(): string | null {
const [language, setLanguage] = useState(() =>
toBcp2(getCurrentKeyboardLanguage()),
)
useEffect(() => {
const sub = addKeyboardLanguageListener(lang => {
setLanguage(toBcp2(lang))
})
return () => sub.remove()
}, [])
return language
}
+6
View File
@@ -0,0 +1,6 @@
/**
* Web stub — keyboard language detection is not available on web.
*/
export function useKeyboardLanguage(): null {
return null
}
+44 -1
View File
@@ -11,7 +11,7 @@ import {
import {sanitizeAppLanguageSetting} from '#/locale/helpers'
import {APP_LANGUAGES, LANGUAGES} from '#/locale/languages'
import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences'
import {atoms as a, web} from '#/alf'
import {atoms as a, useTheme, web} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {Button} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog'
@@ -21,6 +21,8 @@ import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/
import * as Layout from '#/components/Layout'
import * as Select from '#/components/Select'
import {Text} from '#/components/Typography'
import {IS_NATIVE} from '#/env'
import {device, useStorage} from '#/storage'
import * as SettingsList from './components/SettingsList'
const DEDUPED_LANGUAGES = LANGUAGES.filter(
@@ -31,8 +33,12 @@ const DEDUPED_LANGUAGES = LANGUAGES.filter(
type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
export function LanguageSettingsScreen({}: Props) {
const {_} = useLingui()
const t = useTheme()
const langPrefs = useLanguagePrefs()
const setLangPrefs = useLanguagePrefsApi()
const [useKbLang = false, setUseKbLang] = useStorage(device, [
'useKeyboardLanguage',
])
const contentLanguagePrefsControl = useDialogControl()
@@ -234,6 +240,43 @@ export function LanguageSettingsScreen({}: Props) {
/>
</View>
</SettingsList.Group>
{IS_NATIVE && (
<>
<SettingsList.Divider />
<SettingsList.Group iconInset={false}>
<SettingsList.ItemText>
<Trans>Post language</Trans>
</SettingsList.ItemText>
<Toggle.Item
name="use_keyboard_language"
label={_(
msg`Automatically detect post language from keyboard`,
)}
value={useKbLang}
onChange={value => setUseKbLang(value)}
style={[a.w_full, a.gap_md]}>
<Text style={[a.flex_1]}>
<Trans>
Automatically detect post language from keyboard
</Trans>
</Text>
<Toggle.Platform />
</Toggle.Item>
<Text
style={[
a.text_xs,
a.leading_snug,
t.atoms.text_contrast_medium,
a.mt_sm,
]}>
<Trans>
Experimental. When enabled, the composer will default to
your keyboard language.
</Trans>
</Text>
</SettingsList.Group>
</>
)}
</SettingsList.Container>
</Layout.Content>
</Layout.Screen>
+20 -13
View File
@@ -12,7 +12,7 @@ type ApiContext = {
setPrimaryLanguage: (code2: string) => void
setPostLanguage: (commaSeparatedLangCodes: string) => void
setContentLanguages: (code2s: string[]) => void
savePostLanguageToHistory: () => void
savePostLanguageToHistory: (resolvedLanguage?: string) => void
setAppLanguage: (code2: AppLanguage) => void
}
@@ -61,21 +61,28 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
/**
* Saves whatever language codes are currently selected into a history array,
* which is then used to populate the language selector menu.
*
* If `resolvedLanguage` is provided (e.g. from auto-detected keyboard
* language), it will be saved to history instead of the current
* `postLanguage` preference.
*/
savePostLanguageToHistory() {
savePostLanguageToHistory(resolvedLanguage?: string) {
// filter out duplicate `this.postLanguage` if exists, and prepend
// value to start of array
setStateWrapped(s => ({
...s,
postLanguageHistory: [s.postLanguage]
.concat(
s.postLanguageHistory.filter(
commaSeparatedLangCodes =>
commaSeparatedLangCodes !== s.postLanguage,
),
)
.slice(0, 6),
}))
setStateWrapped(s => {
const langToSave = resolvedLanguage ?? s.postLanguage
return {
...s,
postLanguageHistory: [langToSave]
.concat(
s.postLanguageHistory.filter(
commaSeparatedLangCodes =>
commaSeparatedLangCodes !== langToSave,
),
)
.slice(0, 6),
}
})
},
setAppLanguage(code2: AppLanguage) {
setStateWrapped(s => ({...s, appLanguage: code2}))
+6
View File
@@ -61,6 +61,12 @@ export type Device = {
activitySubscriptionsNudged?: boolean
threadgateNudged?: boolean
/**
* Whether to automatically detect post language from the keyboard language.
* Experimental feature, opt-in.
*/
useKeyboardLanguage?: boolean
/**
* Policy update overlays. New IDs are required for each new announcement.
*/
+49 -5
View File
@@ -70,6 +70,7 @@ import {
type SupportedMimeTypes,
} from '#/lib/constants'
import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
import {useKeyboardLanguage} from '#/lib/hooks/useKeyboardLanguage'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {mimeToExt} from '#/lib/media/video/util'
@@ -134,6 +135,7 @@ import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {IS_ANDROID, IS_IOS, IS_LIQUID_GLASS, IS_NATIVE, IS_WEB} from '#/env'
import {device, useStorage} from '#/storage'
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
import {
draftToComposerPosts,
@@ -243,26 +245,52 @@ export const ComposePost = ({
replyTo?.langs || [],
)
/**
* Automatic keyboard language detection.
*/
const keyboardLanguage = useKeyboardLanguage()
const [autoLangEnabled = false] = useStorage(device, ['useKeyboardLanguage'])
const [manualOverride, setManualOverride] = useState(false)
const isAutoMode = !!autoLangEnabled && !manualOverride
/**
* The currently selected languages of the post. Prefer local temporary
* language suggestion over global lang prefs, if available.
* language suggestion, then auto-detected keyboard language, then global
* lang prefs.
*/
const currentLanguages = useMemo(
() =>
acceptedLanguageSuggestion
? [acceptedLanguageSuggestion]
: toPostLanguages(langPrefs.postLanguage),
[acceptedLanguageSuggestion, langPrefs.postLanguage],
: isAutoMode && keyboardLanguage
? [keyboardLanguage]
: toPostLanguages(langPrefs.postLanguage),
[
acceptedLanguageSuggestion,
isAutoMode,
keyboardLanguage,
langPrefs.postLanguage,
],
)
/**
* When the user selects a language from the composer language selector,
* clear any temporary language suggestions they may have selected
* previously, and any we might try to suggest to them.
* previously, and any we might try to suggest to them. Also locks out
* auto mode for this session.
*/
const onSelectLanguage = () => {
setAcceptedLanguageSuggestion(null)
setReplyToLanguages([])
setManualOverride(true)
}
/**
* Re-enable auto mode when the user taps "Automatic" in the language menu.
*/
const onSelectAutomatic = () => {
setAcceptedLanguageSuggestion(null)
setManualOverride(false)
}
const [composerState, composerDispatch] = useReducer(
@@ -939,7 +967,7 @@ export const ComposePost = ({
originalLocalRefs: composerState.originalLocalRefs,
})
}
setLangPrefs.savePostLanguageToHistory()
setLangPrefs.savePostLanguageToHistory(fromPostLanguages(currentLanguages))
if (initQuote) {
// We want to wait for the quote count to update before we call `onPost`, which will refetch data
whenAppViewReady(agent, initQuote.uri, res => {
@@ -1122,6 +1150,10 @@ export const ComposePost = ({
}}
currentLanguages={currentLanguages}
onSelectLanguage={onSelectLanguage}
onSelectAutomatic={onSelectAutomatic}
keyboardLanguage={keyboardLanguage}
isAutoMode={isAutoMode}
autoLangEnabled={autoLangEnabled}
openGallery={openGallery}
/>
</>
@@ -1823,6 +1855,10 @@ function ComposerFooter({
onAddPost,
currentLanguages,
onSelectLanguage,
onSelectAutomatic,
keyboardLanguage,
isAutoMode,
autoLangEnabled,
openGallery,
}: {
post: PostDraft
@@ -1834,6 +1870,10 @@ function ComposerFooter({
onAddPost: () => void
currentLanguages: string[]
onSelectLanguage?: (language: string) => void
onSelectAutomatic?: () => void
keyboardLanguage: string | null
isAutoMode: boolean
autoLangEnabled: boolean
openGallery?: boolean
}) {
const t = useTheme()
@@ -1992,6 +2032,10 @@ function ComposerFooter({
<PostLanguageSelect
currentLanguages={currentLanguages}
onSelectLanguage={onSelectLanguage}
onSelectAutomatic={onSelectAutomatic}
keyboardLanguage={keyboardLanguage}
isAutoMode={isAutoMode}
autoLangEnabled={autoLangEnabled}
/>
<CharProgress
count={post.shortenedGraphemeLength}
@@ -15,15 +15,24 @@ import * as Dialog from '#/components/Dialog'
import {LanguageSelectDialog} from '#/components/dialogs/LanguageSelectDialog'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe'
import {Keyboard_Stroke2_Corner0_Rounded as KeyboardIcon} from '#/components/icons/Keyboard'
import * as Menu from '#/components/Menu'
import {Text} from '#/components/Typography'
export function PostLanguageSelect({
currentLanguages: currentLanguagesProp,
onSelectLanguage,
onSelectAutomatic,
keyboardLanguage,
isAutoMode,
autoLangEnabled,
}: {
currentLanguages?: string[]
onSelectLanguage?: (language: string) => void
onSelectAutomatic?: () => void
keyboardLanguage?: string | null
isAutoMode?: boolean
autoLangEnabled?: boolean
}) {
const {_} = useLingui()
const langPrefs = useLanguagePrefs()
@@ -46,26 +55,7 @@ export function PostLanguageSelect({
onSelectLanguage?.(langsString)
}
if (
dedupedHistory.length === 1 &&
dedupedHistory[0] === langPrefs.postLanguage
) {
return (
<>
<LanguageBtn onPress={languageDialogControl.open} />
<LanguageSelectDialog
titleText={<Trans>Choose post languages</Trans>}
subtitleText={
<Trans>Select up to 3 languages used in this post</Trans>
}
control={languageDialogControl}
currentLanguages={currentLanguages}
onSelectLanguages={onSelectLanguages}
maxLanguages={3}
/>
</>
)
}
const showAutoItem = !!autoLangEnabled && !!keyboardLanguage
return (
<>
@@ -76,6 +66,31 @@ export function PostLanguageSelect({
)}
</Menu.Trigger>
<Menu.Outer>
{showAutoItem && (
<Menu.Group>
<Menu.Item
label={_(
msg`Keyboard (${codeToLanguageName(
keyboardLanguage,
langPrefs.appLanguage,
)})`,
)}
onPress={() => onSelectAutomatic?.()}>
<Menu.ItemIcon icon={KeyboardIcon} />
<Menu.ItemText>
<Trans>
Keyboard (
{codeToLanguageName(
keyboardLanguage,
langPrefs.appLanguage,
)}
)
</Trans>
</Menu.ItemText>
<Menu.ItemRadio selected={!!isAutoMode} />
</Menu.Item>
</Menu.Group>
)}
<Menu.Group>
{dedupedHistory.map(historyItem => {
const langCodes = historyItem.split(',')
@@ -92,7 +107,9 @@ export function PostLanguageSelect({
}}>
<Menu.ItemText>{langName}</Menu.ItemText>
<Menu.ItemRadio
selected={currentLanguages.includes(historyItem)}
selected={
!isAutoMode && currentLanguages.includes(historyItem)
}
/>
</Menu.Item>
)