Skip to content

Commit c33339a

Browse files
committed
Add auto-select existing languages feature
1 parent 2f64a18 commit c33339a

File tree

5 files changed

+106
-0
lines changed

5 files changed

+106
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
## [Unreleased]
66

7+
### Added
8+
- Auto-select existing languages option in the Select Languages dialog to automatically detect and select languages that already exist in the project.
9+
710
### Fixed
811
- ExceptionInInitializerError when opening plguin.
912

src/main/kotlin/com/airsaid/localization/action/TranslateAction.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ private fun isTranslatable(values: List<PsiElement>, valueService: AndroidValues
9898

9999
private fun showSelectLanguageDialog(project: Project, values: List<PsiElement>, valueFile: PsiFile) {
100100
val dialog = SelectLanguagesDialog(project)
101+
102+
// Set resource directory for auto-selecting existing languages
103+
val resourceDir = valueFile.virtualFile.parent.parent
104+
dialog.setResourceDir(resourceDir)
105+
101106
dialog.setOnClickListener(object : SelectLanguagesDialog.OnClickListener {
102107
override fun onClickListener(selectedLanguage: List<Lang>) {
103108
val translationTask = TranslateTask(project, "Translating...", selectedLanguage, values, valueFile)

src/main/kotlin/com/airsaid/localization/constant/Constants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ object Constants {
2929
const val KEY_FAVORITE_LANGUAGES = "$PLUGIN_ID.favorite_languages"
3030
const val KEY_IS_OVERWRITE_EXISTING_STRING = "$PLUGIN_ID.is_overwrite_existing_string"
3131
const val KEY_IS_OPEN_TRANSLATED_FILE = "$PLUGIN_ID.is_open_translated_file"
32+
const val KEY_IS_AUTO_SELECT_EXISTING = "$PLUGIN_ID.is_auto_select_existing"
3233
}

src/main/kotlin/com/airsaid/localization/ui/SelectLanguagesDialog.kt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import com.airsaid.localization.utils.LanguageUtil
5252
import com.intellij.ide.util.PropertiesComponent
5353
import com.intellij.openapi.options.ShowSettingsUtil
5454
import com.intellij.openapi.project.Project
55+
import com.intellij.openapi.vfs.VirtualFile
5556
import java.awt.Dimension
5657
import java.awt.Toolkit
5758
import kotlin.math.roundToInt
@@ -84,8 +85,10 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
8485
private val selectedLanguages = mutableStateListOf<Lang>()
8586
private val overwriteExistingState = mutableStateOf(false)
8687
private val openTranslatedFileState = mutableStateOf(false)
88+
private val autoSelectExistingState = mutableStateOf(false)
8789

8890
private var stateInitialized by mutableStateOf(false)
91+
private var resourceDir: VirtualFile? = null
8992

9093
private var onClickListener: OnClickListener? = null
9194

@@ -102,6 +105,15 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
102105
onClickListener = listener
103106
}
104107

108+
/**
109+
* Sets the resource directory to enable auto-selecting existing languages.
110+
*
111+
* @param resourceDir The resource directory containing values folders.
112+
*/
113+
fun setResourceDir(resourceDir: VirtualFile) {
114+
this.resourceDir = resourceDir
115+
}
116+
105117
@Composable
106118
override fun Content() {
107119
LaunchedEffect(Unit) {
@@ -110,6 +122,13 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
110122
}
111123
}
112124

125+
// Monitor changes to auto-select setting
126+
LaunchedEffect(autoSelectExistingState.value) {
127+
if (stateInitialized && autoSelectExistingState.value) {
128+
selectExistingLanguages()
129+
}
130+
}
131+
113132
if (!stateInitialized) {
114133
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
115134
CircularProgressIndicator()
@@ -132,10 +151,13 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
132151
selectedLanguages = selectedLanguages,
133152
overwriteExistingChecked = overwriteExistingState.value,
134153
openTranslatedFileChecked = openTranslatedFileState.value,
154+
autoSelectExistingChecked = autoSelectExistingState.value,
155+
hasResourceDir = resourceDir != null,
135156
onSelectAllChanged = { selectAll(languages, it) },
136157
onFavoriteSelectAllChanged = { selectAll(favoriteLanguages, it) },
137158
onOverwriteChanged = { checked -> overwriteExistingState.value = checked },
138159
onOpenTranslatedFileChanged = { checked -> openTranslatedFileState.value = checked },
160+
onAutoSelectExistingChanged = { checked -> autoSelectExistingState.value = checked },
139161
onLanguageToggled = { lang, checked -> selectLanguage(lang, checked) },
140162
onFavoriteToggle = { lang, isFavorite -> setFavoriteLanguage(lang, isFavorite) },
141163
onOpenSettings = { openPluginSettings() },
@@ -146,6 +168,7 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
146168
LanguageUtil.saveSelectedLanguages(project, selectedLanguages)
147169
properties().setValue(Constants.KEY_IS_OVERWRITE_EXISTING_STRING, overwriteExistingState.value)
148170
properties().setValue(Constants.KEY_IS_OPEN_TRANSLATED_FILE, openTranslatedFileState.value)
171+
properties().setValue(Constants.KEY_IS_AUTO_SELECT_EXISTING, autoSelectExistingState.value)
149172
onClickListener?.onClickListener(selectedLanguages.toList())
150173
}
151174

@@ -183,6 +206,12 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
183206

184207
overwriteExistingState.value = properties.getBoolean(Constants.KEY_IS_OVERWRITE_EXISTING_STRING)
185208
openTranslatedFileState.value = properties.getBoolean(Constants.KEY_IS_OPEN_TRANSLATED_FILE)
209+
autoSelectExistingState.value = properties.getBoolean(Constants.KEY_IS_AUTO_SELECT_EXISTING)
210+
211+
// If auto-select existing languages is enabled and resource directory is available, auto-select existing languages
212+
if (autoSelectExistingState.value) {
213+
selectExistingLanguages()
214+
}
186215

187216
stateInitialized = true
188217
}
@@ -216,6 +245,15 @@ class SelectLanguagesDialog(private val project: Project) : ComposeDialog(projec
216245
LanguageUtil.saveFavoriteLanguages(project, favoriteLanguages)
217246
}
218247

248+
private fun selectExistingLanguages() {
249+
resourceDir?.let { resDir ->
250+
val existingLanguages = LanguageUtil.getExistingProjectLanguages(resDir, supportedLanguages)
251+
existingLanguages.forEach { lang ->
252+
selectLanguage(lang, true)
253+
}
254+
}
255+
}
256+
219257
private fun properties(): PropertiesComponent {
220258
return PropertiesComponent.getInstance(project)
221259
}
@@ -254,10 +292,13 @@ private fun SelectLanguagesContent(
254292
selectedLanguages: SnapshotStateList<Lang>,
255293
overwriteExistingChecked: Boolean,
256294
openTranslatedFileChecked: Boolean,
295+
autoSelectExistingChecked: Boolean,
296+
hasResourceDir: Boolean,
257297
onSelectAllChanged: (Boolean) -> Unit,
258298
onFavoriteSelectAllChanged: (Boolean) -> Unit,
259299
onOverwriteChanged: (Boolean) -> Unit,
260300
onOpenTranslatedFileChanged: (Boolean) -> Unit,
301+
onAutoSelectExistingChanged: (Boolean) -> Unit,
261302
onLanguageToggled: (Lang, Boolean) -> Unit,
262303
onFavoriteToggle: (Lang, Boolean) -> Unit,
263304
onOpenSettings: () -> Unit,
@@ -282,10 +323,13 @@ private fun SelectLanguagesContent(
282323
favoriteSelectAll = favoriteSelectAllChecked,
283324
overwriteExisting = overwriteExistingChecked,
284325
openTranslatedFile = openTranslatedFileChecked,
326+
autoSelectExisting = autoSelectExistingChecked,
327+
hasResourceDir = hasResourceDir,
285328
onSelectAllChanged = onSelectAllChanged,
286329
onFavoriteSelectAllChanged = onFavoriteSelectAllChanged,
287330
onOverwriteChanged = onOverwriteChanged,
288331
onOpenTranslatedFileChanged = onOpenTranslatedFileChanged,
332+
onAutoSelectExistingChanged = onAutoSelectExistingChanged,
289333
onLanguageToggled = onLanguageToggled,
290334
onFavoriteToggle = onFavoriteToggle,
291335
modifier = Modifier.weight(1f, fill = true),
@@ -307,10 +351,13 @@ private fun LanguagesCard(
307351
favoriteSelectAll: Boolean,
308352
overwriteExisting: Boolean,
309353
openTranslatedFile: Boolean,
354+
autoSelectExisting: Boolean,
355+
hasResourceDir: Boolean,
310356
onSelectAllChanged: (Boolean) -> Unit,
311357
onFavoriteSelectAllChanged: (Boolean) -> Unit,
312358
onOverwriteChanged: (Boolean) -> Unit,
313359
onOpenTranslatedFileChanged: (Boolean) -> Unit,
360+
onAutoSelectExistingChanged: (Boolean) -> Unit,
314361
onLanguageToggled: (Lang, Boolean) -> Unit,
315362
onFavoriteToggle: (Lang, Boolean) -> Unit,
316363
modifier: Modifier = Modifier,
@@ -361,6 +408,9 @@ private fun LanguagesCard(
361408
onOverwriteChanged = onOverwriteChanged,
362409
openTranslatedFile = openTranslatedFile,
363410
onOpenTranslatedFileChanged = onOpenTranslatedFileChanged,
411+
autoSelectExisting = autoSelectExisting,
412+
hasResourceDir = hasResourceDir,
413+
onAutoSelectExistingChanged = onAutoSelectExistingChanged,
364414
)
365415

366416
OutlinedTextField(
@@ -530,6 +580,9 @@ private fun OptionsSection(
530580
onOverwriteChanged: (Boolean) -> Unit,
531581
openTranslatedFile: Boolean,
532582
onOpenTranslatedFileChanged: (Boolean) -> Unit,
583+
autoSelectExisting: Boolean,
584+
hasResourceDir: Boolean,
585+
onAutoSelectExistingChanged: (Boolean) -> Unit,
533586
) {
534587
FlowRow(
535588
horizontalArrangement = Arrangement.spacedBy(16.dp),
@@ -547,6 +600,14 @@ private fun OptionsSection(
547600
checked = openTranslatedFile,
548601
onCheckedChange = onOpenTranslatedFileChanged,
549602
)
603+
if (hasResourceDir) {
604+
OptionItem(
605+
text = "Auto-select existing languages",
606+
tooltip = "Automatically select languages that already exist in your project when opening this dialog.",
607+
checked = autoSelectExisting,
608+
onCheckedChange = onAutoSelectExistingChanged,
609+
)
610+
}
550611
}
551612
}
552613

src/main/kotlin/com/airsaid/localization/utils/LanguageUtil.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.airsaid.localization.translate.lang.Lang
2222
import com.airsaid.localization.translate.lang.Languages
2323
import com.intellij.ide.util.PropertiesComponent
2424
import com.intellij.openapi.project.Project
25+
import com.intellij.openapi.vfs.VirtualFile
2526
import org.apache.http.util.TextUtils
2627

2728
/**
@@ -85,6 +86,41 @@ object LanguageUtil {
8586
return language.joinToString(SEPARATOR_SELECTED_LANGUAGES_CODE) { it.code }
8687
}
8788

89+
/**
90+
* Get languages that already exist in the project by scanning the resource directories.
91+
*
92+
* @param resourceDir the resource directory (parent of values directories).
93+
* @param supportedLanguages the list of supported languages from translator.
94+
* @return list of languages that have corresponding values directories in the project.
95+
*/
96+
fun getExistingProjectLanguages(resourceDir: VirtualFile, supportedLanguages: List<Lang>): List<Lang> {
97+
val existingLanguages = mutableListOf<Lang>()
98+
99+
for (child in resourceDir.children) {
100+
if (child.isDirectory) {
101+
val dirName = child.name
102+
103+
if (dirName == "values") {
104+
// Default values directory represents the default language (usually English)
105+
// We'll look for a language with empty directoryName or "en" code
106+
val defaultLang = supportedLanguages.find { it.directoryName.isBlank() || it.code == "en" }
107+
defaultLang?.let { existingLanguages.add(it) }
108+
} else if (dirName.startsWith("values-")) {
109+
val languageCode = dirName.substring(7) // Remove "values-" prefix
110+
111+
// Find matching language by directory name
112+
val matchingLang = supportedLanguages.find { lang ->
113+
lang.directoryName == languageCode
114+
}
115+
116+
matchingLang?.let { existingLanguages.add(it) }
117+
}
118+
}
119+
}
120+
121+
return existingLanguages.distinct()
122+
}
123+
88124
private fun parseStoredLanguageCodes(value: String?): List<String> {
89125
if (value.isNullOrEmpty()) return emptyList()
90126

0 commit comments

Comments
 (0)