11<script lang="ts">
22import type { MenuOption } from ' naive-ui'
3- import { NButton , NCheckbox , NCheckboxGroup , NFlex , NLayout , NLayoutFooter , NLayoutSider , NMenu } from ' naive-ui'
3+ import { NButton , NCheckbox , NCheckboxGroup , NFlex , NLayout , NLayoutFooter , NLayoutSider , NMenu , NText } from ' naive-ui'
44import { computed , h , ref , watchEffect } from ' vue'
55import BasicConfig from ' ./BasicConfig.vue'
66import FooterButtons from ' ./FooterButtons.vue'
@@ -13,11 +13,17 @@ const languageName = new Intl.DisplayNames(navigator.language, { type: 'language
1313
1414function getNameOf(code : string ) {
1515 try {
16- return languageName .of (code ) ?? code
16+ const name = languageName .of (code )
17+ if (name && name !== code ) {
18+ return name
19+ }
1720 }
18- catch { // e.g. code === '*' (m17n math-latex)
19- return code
21+ catch {}
22+ const name = window .fcitx .getLanguageName (code )
23+ if (name ) {
24+ return name
2025 }
26+ return ` ${t (' Unknown' )} - ${code } `
2127}
2228 </script >
2329
@@ -31,6 +37,9 @@ const props = defineProps<{
3137 onClose: () => void
3238}>()
3339
40+ const EN = ' en'
41+ const popularIMs = [' keyboard-us' , ' pinyin' , ' shuangpin' , ' wbx' , ' rime' , ' mozc' , ' hallelujah' ]
42+
3443const enabledIMs = computed (() => props .inputMethods .map (({ name }) => name ))
3544
3645const selectedInputMethod = ref (props .inputMethod )
@@ -70,6 +79,7 @@ function labelWithMinus(option: MenuOption) {
7079const collapsed = ref (false )
7180const adding = ref (false )
7281
82+ const currentLanguages = navigator .languages .map (lang => lang .split (' -' )[0 ])
7383const selectedLanguage = ref <string | null >(null )
7484
7585const languageOptions = ref <{
@@ -90,7 +100,7 @@ watchEffect(() => {
90100 map = {}
91101 languageOfIM = {}
92102 for (const im of window .fcitx .getAllInputMethods ()) {
93- const code = im .languageCode .replace (' _' , ' -' );
103+ const code = im .languageCode .replace (' _' , ' -' ) || ' und ' ;
94104 (map [code ] = map [code ] || []).push ({
95105 name: im .name ,
96106 displayName: im .displayName ,
@@ -99,25 +109,29 @@ watchEffect(() => {
99109 }
100110 languageOptions .value = []
101111 const sortedLanguageCodes = Object .keys (map ).sort ((a : string , b : string ) => {
102- if (! a ) {
103- return 1
104- }
105- if (! b ) {
112+ // Pin English.
113+ if (a === EN ) {
106114 return - 1
107115 }
108- const la = getNameOf (a )
109- const lb = getNameOf (b )
110- if (a === la && b !== lb ) {
116+ if (b === EN ) {
111117 return 1
112118 }
113- if (a !== la && b === lb ) {
119+ // Pin browser languages.
120+ const aIsCurrent = currentLanguages .includes (a .split (' -' )[0 ])
121+ const bIsCurrent = currentLanguages .includes (b .split (' -' )[0 ])
122+ if (aIsCurrent && ! bIsCurrent ) {
114123 return - 1
115124 }
125+ if (! aIsCurrent && bIsCurrent ) {
126+ return 1
127+ }
128+ const la = getNameOf (a )
129+ const lb = getNameOf (b )
116130 return la .localeCompare (lb )
117131 })
118132 for (const languageCode of sortedLanguageCodes ) {
119133 languageOptions .value .push ({
120- label: languageCode ? getNameOf (languageCode ) : ' Unknown ' ,
134+ label: getNameOf (languageCode ),
121135 key: languageCode ,
122136 })
123137 }
@@ -127,7 +141,21 @@ const inputMethodsForLanguage = computed(() => {
127141 if (selectedLanguage .value === null ) {
128142 return []
129143 }
130- return map [selectedLanguage .value ].filter (({ name }) => ! enabledIMs .value .includes (name ))
144+ return map [selectedLanguage .value ].filter (({ name }) => ! enabledIMs .value .includes (name )).sort ((a , b ) => {
145+ // Pin popular input methods.
146+ const ia = popularIMs .indexOf (a .name )
147+ const ib = popularIMs .indexOf (b .name )
148+ if (ia >= 0 && ib < 0 ) {
149+ return - 1
150+ }
151+ if (ia < 0 && ib >= 0 ) {
152+ return 1
153+ }
154+ if (ia >= 0 && ib >= 0 ) {
155+ return ia - ib
156+ }
157+ return a .displayName .localeCompare (b .displayName )
158+ })
131159})
132160
133161const imsToAdd = ref <string []>([])
@@ -142,9 +170,11 @@ const onlyShowCurrentLanguage = ref(false)
142170
143171const filteredLanguageOptions = computed (() => {
144172 if (onlyShowCurrentLanguage .value ) {
145- const currentLanguage = navigator .language .split (' -' )[0 ]
146173 const languages = new Set (enabledIMs .value .map (name => languageOfIM [name ]).filter (code => code ))
147- languages .add (currentLanguage )
174+ languages .add (EN )
175+ for (const lang of currentLanguages ) {
176+ languages .add (lang )
177+ }
148178 return languageOptions .value .filter (({ key }) => languages .has (key .split (' -' )[0 ]))
149179 }
150180 return languageOptions .value
@@ -225,8 +255,11 @@ const filteredLanguageOptions = computed(() => {
225255 v-for =" im of inputMethodsForLanguage"
226256 :key =" im.name"
227257 :value =" im.name"
228- :label =" im.displayName"
229- />
258+ >
259+ <NText :strong =" popularIMs.includes(im.name)" >
260+ {{ im.displayName }}
261+ </NText >
262+ </NCheckbox >
230263 </NFlex >
231264 </NCheckboxGroup >
232265 </NLayout >
0 commit comments