Skip to content

Commit

Permalink
Merge branch 'next' into compat/203-212
Browse files Browse the repository at this point in the history
  • Loading branch information
YiiGuxing committed Nov 19, 2023
2 parents 7e9633c + 2020dd8 commit e04dc23
Show file tree
Hide file tree
Showing 15 changed files with 70 additions and 50 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Translation Plugin Changelog

## [Unreleased]

- Fix the problem of missing required parameters for document translation in the Youdao translation engine.
- Other known bug fixes.
- 修复有道翻译引擎文档翻译缺少必需参数的问题
- 其他已知问题修复

## [3.5.5] (2023/10/15)

- Added support for RustRover and the new Rust plugin.
- DeepL Translator now supports Ukrainian and Korean.
- Compatible with 2023.3.
Expand Down Expand Up @@ -436,7 +444,8 @@
- 支持单词拆分。翻译变量名或方法名时更方便
- Bug修复

[Unreleased]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.4...HEAD
[Unreleased]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.5...HEAD
[3.5.5]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.4...v3.5.5
[3.5.4]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.3...v3.5.4
[3.5.3]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.2...v3.5.3
[3.5.2]: https://github.com/YiiGuxing/TranslationPlugin/compare/v3.5.1...v3.5.2
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ plugins {

fun properties(key: String) = providers.gradleProperty(key)
fun environment(key: String) = providers.environmentVariable(key)
fun dateValue(pattern: String) = LocalDate.now(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern(pattern))
fun dateValue(pattern: String): String = LocalDate.now(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern(pattern))

val autoSnapshotVersionEnv: Provider<Boolean> = environment("AUTO_SNAPSHOT_VERSION").map(String::toBoolean).orElse(true)
val snapshotVersionPart: Provider<String> = properties("autoSnapshotVersion")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pluginGroup = cn.yiiguxing.plugin.translate
pluginRepositoryUrl = https://github.com/YiiGuxing/TranslationPlugin

# SemVer format -> https://semver.org
pluginMajorVersion = 3.5.5
pluginMajorVersion = 3.5.6
pluginPreReleaseVersion =
pluginBuildMetadata = 203u212
autoSnapshotVersion = true
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[versions]
# libraries
jsoup = "1.16.1"
jsoup = "1.16.2"
dbutils = "1.8.1"
mp3spi = "1.9.5.4"
junit = "4.13.2"

# plugins
kotlin = "1.9.10"
kotlin = "1.9.20"
kover = "0.7.4"
qodana = "0.1.13"
changelog = "2.2.0"
Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/cn/yiiguxing/plugin/translate/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.intellij.util.messages.Topic
import com.intellij.util.xmlb.XmlSerializerUtil
import com.intellij.util.xmlb.annotations.Tag
import com.intellij.util.xmlb.annotations.Transient
import org.jetbrains.concurrency.runAsync
import kotlin.properties.Delegates

/**
Expand Down Expand Up @@ -175,8 +176,10 @@ class Settings : PersistentStateComponent<Settings> {

LOG.d("===== Settings Data Version: $dataVersion =====")
if (dataVersion < CURRENT_DATA_VERSION) {
migrate()
properties.setValue(DATA_VERSION_KEY, CURRENT_DATA_VERSION, 0)
runAsync {
migrate()
properties.setValue(DATA_VERSION_KEY, CURRENT_DATA_VERSION, 0)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import cn.yiiguxing.plugin.translate.util.concurrent.errorOnUiThread
import cn.yiiguxing.plugin.translate.util.concurrent.expireWith
import cn.yiiguxing.plugin.translate.util.concurrent.finishOnUiThread
import cn.yiiguxing.plugin.translate.util.concurrent.successOnUiThread
import com.intellij.ide.DataManager
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.PopupAction
import com.intellij.openapi.actionSystem.Presentation
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.ex.ComboBoxAction
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.project.DumbAware
Expand Down Expand Up @@ -64,12 +62,14 @@ class SwitchTranslationEngineAction : ComboBoxAction(), DumbAware, PopupAction {
}

isActionPerforming = true
val component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT)
val expireDisposable = getDisposable()
runAsync { TranslationEngineActionGroup() }
.expireWith(expireDisposable)
.successOnUiThread { group ->
if (isActionPerforming && !project.isDisposed) {
group.createActionPopup(e.dataContext).showCenteredInCurrentWindow(project)
val dataContext = DataManager.getInstance().getDataContext(component)
group.createActionPopup(dataContext).showCenteredInCurrentWindow(project)
}
}
.finishOnUiThread(ModalityState.any()) { isActionPerforming = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TranslateService private constructor() : Disposable {
var translator: Translator = DEFAULT_TRANSLATOR
private set

private val listeners = mutableMapOf<ListenerKey, MutableSet<TranslateListener>>()
private val listeners = mutableMapOf<ListenerKey, MutableSet<ListenerInfo>>()

init {
setTranslator(Settings.instance.translator)
Expand Down Expand Up @@ -78,19 +78,20 @@ class TranslateService private constructor() : Disposable {
}

val key = ListenerKey(text, srcLang, targetLang)
val listenerInfo = ListenerInfo(modalityState, listener)
listeners[key]?.let {
it += listener
it += listenerInfo
return
}
listeners[key] = mutableSetOf(listener)
listeners[key] = mutableSetOf(listenerInfo)

executeOnPooledThread {
try {
with(translator) {
translate(text, srcLang, targetLang).let { translation ->
translation.favoriteId = getFavoriteId(translation)
CacheService.putMemoryCache(text, srcLang, targetLang, id, translation)
invokeLater(modalityState) { listeners.run(key) { onSuccess(translation) } }
listeners.run(key) { onSuccess(translation) }
}
}
} catch (error: Throwable) {
Expand All @@ -101,7 +102,7 @@ class TranslateService private constructor() : Disposable {
// 将异常写入IDE异常池,以便用户反馈
investigate(text, srcLang, targetLang, error)
}
invokeLater(modalityState) { listeners.run(key) { onError(error) } }
listeners.run(key) { onError(error) }
}
}
}
Expand All @@ -123,11 +124,13 @@ class TranslateService private constructor() : Disposable {
LOG.error("Translation error[${translator.id}]: ${error.message}", error, requestAttachment)
}

private inline fun MutableMap<ListenerKey, MutableSet<TranslateListener>>.run(
private inline fun MutableMap<ListenerKey, MutableSet<ListenerInfo>>.run(
key: ListenerKey,
action: TranslateListener.() -> Unit
crossinline action: TranslateListener.() -> Unit
) {
remove(key)?.forEach { it.action() }
remove(key)?.forEach { info ->
invokeLater(info.modalityState) { info.listener.action() }
}
}

private fun Translation.updateFavoriteStateIfNeed(favorites: List<WordBookItem>) {
Expand Down Expand Up @@ -189,6 +192,8 @@ class TranslateService private constructor() : Disposable {

private data class ListenerKey(val text: String, val srcLang: Lang, val targetLang: Lang)

private data class ListenerInfo(val modalityState: ModalityState, val listener: TranslateListener)

companion object {
val DEFAULT_TRANSLATOR: Translator by lazy {
if (Locale.getDefault() == Locale.CHINA) MicrosoftTranslator else GoogleTranslator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,16 @@ object YoudaoTranslator : AbstractTranslator(), DocumentationTranslator {
srcLang: Lang,
targetLang: Lang
): Document = checkError {
documentation.translateBody { bodyHTML ->
translateDocumentation(bodyHTML, srcLang, targetLang)
}
// Youdao does not support auto detection language for documentation translation
val fixedSrcLang = srcLang.takeIf { it != Lang.AUTO } ?: Lang.ENGLISH
val fixedTargetLang = targetLang.takeIf { it != Lang.AUTO } ?: super.defaultLangForLocale
documentation.translateBody { bodyHTML -> translateDocumentation(bodyHTML, fixedSrcLang, fixedTargetLang) }
}

private fun translateDocumentation(documentation: String, srcLang: Lang, targetLang: Lang): String {
// Youdao does not support auto detection target language for documentation translation
val fixedTargetLang = targetLang.takeIf { it != Lang.AUTO } ?: super.defaultLangForLocale
val client = SimpleTranslateClient(this, ::callForDocumentation, ::parseTranslationForDocumentation)
client.updateCacheKey { it.update("DOCUMENTATION".toByteArray()) }
return client.execute(documentation, srcLang, fixedTargetLang).translation ?: ""
return client.execute(documentation, srcLang, targetLang).translation ?: ""
}

private fun callForDocumentation(text: String, srcLang: Lang, targetLang: Lang): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class TranslationFailedComponent : JPanel(), Disposable {
runAsync { TranslationEngineActionGroup() }
.expireWith(this)
.successOnUiThread(widgetRef) { widget, group ->
val button = widget.optionButton
val button = widget.optionButton.takeIf { it.isShowing } ?: return@successOnUiThread
var offsetLeft: Int
var offsetRight: Int
var offsetBottom: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import cn.yiiguxing.plugin.translate.util.concurrent.successOnUiThread
import cn.yiiguxing.plugin.translate.util.invokeLaterIfNeeded
import com.intellij.ide.DataManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.IconLikeCustomStatusBarWidget
Expand All @@ -41,6 +42,8 @@ class TranslationWidget(private val project: Project) : WithIconAndArrows(), Ico

private var isLoadingTranslationEngines = false

private var isDisposed = false

init {
setTextAlignment(CENTER_ALIGNMENT)
}
Expand Down Expand Up @@ -102,6 +105,10 @@ class TranslationWidget(private val project: Project) : WithIconAndArrows(), Ico
}

private fun showGotItTooltipIfNeed() {
if (isDisposed) {
return
}

val id = "${TranslationPlugin.PLUGIN_ID}.tooltip.new.translation.engines.openai"
val message = message("got.it.tooltip.text.new.translation.engines")
GotItTooltip(id, message, this)
Expand All @@ -124,12 +131,17 @@ class TranslationWidget(private val project: Project) : WithIconAndArrows(), Ico
val at = Point(0, -popup.content.preferredSize.height)
popup.show(RelativePoint(widget, at))
}
.onError {
logger<TranslationWidget>().warn("Failed to show translation engines popup.", it)
}
.finishOnUiThread(widgetRef, ModalityState.any()) { widget, _ ->
widget.isLoadingTranslationEngines = false
}
.disposeAfterProcessing(widgetRef)
}

override fun dispose() {}
override fun dispose() {
isDisposed = true
}

}
28 changes: 10 additions & 18 deletions src/main/kotlin/cn/yiiguxing/plugin/translate/util/LruCache.kt
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ open class LruCache<K, V>(maxSize: Int) {
val previous: V? = synchronized(this) {
putCount++
size += safeSizeOf(key, value)
map.put(key, value)?.apply {
size -= safeSizeOf(key, this@apply)
}
map.put(key, value)?.also { size -= safeSizeOf(key, it) }
}
previous?.let {
entryRemoved(false, key, it, value)
Expand All @@ -183,17 +181,15 @@ open class LruCache<K, V>(maxSize: Int) {
}

/**
* Remove the eldest entries until the total of remaining entries is at or
* below the requested size.
* Remove the eldest entries until the total of remaining entries is at or below the requested size.
*
* @param maxSize the maximum size of the cache before returning. May be -1
* to evict even 0-sized elements.
* @param maxSize the maximum size of the cache before returning. Maybe -1 to evict even 0-sized elements.
*/
fun trimToSize(maxSize: Int) {
while (true) {
val toEvict = synchronized(this) {
check(!(size < 0 || map.isEmpty() && size != 0)) {
javaClass.name + ".sizeOf() is reporting inconsistent results!"
"${javaClass.name}.sizeOf() is reporting inconsistent results! size=$size."
}

if (size <= maxSize || map.isEmpty()) {
Expand All @@ -217,14 +213,10 @@ open class LruCache<K, V>(maxSize: Int) {
* @return the previous value mapped by [key].
*/
fun remove(key: K & Any): V? {
val previous: V? = synchronized(this) {
map.remove(key)?.apply {
size -= safeSizeOf(key, this@apply)
}
}

return previous?.apply {
entryRemoved(false, key, this@apply, null)
return synchronized(this) {
map.remove(key)?.also { previous -> size -= safeSizeOf(key, previous) }
}?.also { previous ->
entryRemoved(false, key, previous, null)
}
}

Expand All @@ -246,8 +238,8 @@ open class LruCache<K, V>(maxSize: Int) {
}

if (removed.isNotEmpty()) {
removed.forEach {
entryRemoved(false, it.key, it.value, null)
removed.forEach { (key, value) ->
entryRemoved(false, key, value, null)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/messages/TranslationBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,6 @@ youdao.settings.dialog.hint=<html>You may need to create a translation applicati
<a href="https://ai.youdao.com/console">Youdao Console</a> \
to obtain an Application ID and Application Key, and enable these services: \
<span style="color: {0};">Text Translation</span>, \
<span style="color: {0};">Rich Text Translation</span> and \
<span style="color: {0};">Webpage Translation</span> and \
<span style="color: {0};">Domain-specific Translation</span> \
(optional)</html>
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,6 @@ youdao.settings.dialog.hint=<html>Application IDとApplication Keyを取得し
<a href="https://ai.youdao.com/console">Youdao Console</a> \
ページで翻訳アプリケーションを作成する必要があるかもしれません: \
<span style="color: {0};">テキスト翻訳</span>、\
<span style="color: {0};">リッチテキスト翻訳</span>、および \
<span style="color: {0};">ウェブページの翻訳</span>、および \
<span style="color: {0};">ドメイン特化翻訳</span> \
(オプション)</html>
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,6 @@ youdao.settings.dialog.hint=<html>Application ID와 Application Key를 얻기
<a href="https://ai.youdao.com/console">Youdao Console</a> \
페이지에서 번역 애플리케이션을 생성해야 할 수도 있으며, 다음 서비스를 활성화해야 합니다: \
<span style="color: {0};">텍스트 번역</span>, \
<span style="color: {0};">리치 텍스트 번역</span> \
<span style="color: {0};">웹페이지 번역</span> \
그리고 <span style="color: {0};">도메인 특화 번역</span> \
(선택 사항)</html>
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,6 @@ youdao.settings.dialog.hint=<html>您可能需要在您的\
<a href="https://ai.youdao.com/console">有道智云控制台</a>\
页面创建一个翻译应用以获取应用ID和应用秘钥,并开通这些服务:\
<span style="color: {0};">文本翻译</span>、\
<span style="color: {0};">富文本翻译</span> 和 \
<span style="color: {0};">网页翻译</span> 和 \
<span style="color: {0};">领域化翻译</span>\
(可选)</html>

0 comments on commit e04dc23

Please sign in to comment.