commit
c1ad9602d8
17
CHANGELOG.md
17
CHANGELOG.md
@ -3,13 +3,26 @@
|
||||
# easy-i18n Changelog
|
||||
|
||||
## [Unreleased]
|
||||
### THANKS FOR OVER 1000 DOWNLOADS SO FAR!
|
||||
|
||||
### Added
|
||||
- Basic support for json array values
|
||||
- Settings option to opt-out code assistance inside editor
|
||||
- Support key completion and annotation for Kotlin language
|
||||
- Example locale files for all configuration options
|
||||
- Donation links on GitHub to support development
|
||||
|
||||
### Changed
|
||||
- Update dependencies
|
||||
- Migrate gradle build script
|
||||
|
||||
## [1.3.0]
|
||||
### Added
|
||||
- Scroll to created / edited translation inside Tree-/Table-View
|
||||
- Support for working with multiple projects at once
|
||||
|
||||
### Changed
|
||||
- Updated dependencies
|
||||
- Update dependencies
|
||||
- Load translations even if ui tool window is not opened
|
||||
|
||||
### Fixed
|
||||
@ -28,7 +41,7 @@
|
||||
- Support for IntelliJ 2021.1
|
||||
|
||||
### Changed
|
||||
- Updated dependencies
|
||||
- Update dependencies
|
||||
|
||||
### Fixed
|
||||
- Exception during i18n key completion / annotation
|
||||
|
@ -3,6 +3,7 @@
|
||||

|
||||
[](https://plugins.jetbrains.com/plugin/16316)
|
||||
[](https://plugins.jetbrains.com/plugin/16316)
|
||||
[](https://paypal.me/marhalide)
|
||||
|
||||
<!-- Plugin description -->
|
||||
This is an easy plugin to manage internationalization for JSON or Resource-Bundle(Properties) based locale files.
|
||||
@ -48,6 +49,11 @@ Most common use case is for translating Webapps or simple Java Applications. Tra
|
||||
- Select the created directory (optional: define the preferred locale to view) and press Ok
|
||||
- Translations can now be created / edited or deleted
|
||||
|
||||
Examples for the configuration can be found in the [/example](https://github.com/marhali/easy-i18n/tree/main/example) folder.
|
||||
|
||||
## Donation
|
||||
If the project helps you to reduce development time, you can give me a [cup of coffee](https://paypal.me/marhalide) :)
|
||||
|
||||
---
|
||||
Plugin based on the [IntelliJ Platform Plugin Template][template].
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import io.gitlab.arturbosch.detekt.Detekt
|
||||
import org.jetbrains.changelog.closure
|
||||
import org.jetbrains.changelog.markdownToHTML
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
@ -11,7 +10,7 @@ plugins {
|
||||
// Kotlin support
|
||||
id("org.jetbrains.kotlin.jvm") version "1.5.10"
|
||||
// gradle-intellij-plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
|
||||
id("org.jetbrains.intellij") version "0.7.3"
|
||||
id("org.jetbrains.intellij") version "1.0"
|
||||
// gradle-changelog-plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
|
||||
id("org.jetbrains.changelog") version "1.1.2"
|
||||
// detekt linter - read more: https://detekt.github.io/detekt/gradle.html
|
||||
@ -26,7 +25,6 @@ version = properties("pluginVersion")
|
||||
// Configure project's dependencies
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.17.1")
|
||||
@ -35,14 +33,14 @@ dependencies {
|
||||
// Configure gradle-intellij-plugin plugin.
|
||||
// Read more: https://github.com/JetBrains/gradle-intellij-plugin
|
||||
intellij {
|
||||
pluginName = properties("pluginName")
|
||||
version = properties("platformVersion")
|
||||
type = properties("platformType")
|
||||
downloadSources = properties("platformDownloadSources").toBoolean()
|
||||
updateSinceUntilBuild = true
|
||||
pluginName.set(properties("pluginName"))
|
||||
version.set(properties("platformVersion"))
|
||||
type.set(properties("platformType"))
|
||||
downloadSources.set(properties("platformDownloadSources").toBoolean())
|
||||
updateSinceUntilBuild.set(true)
|
||||
|
||||
// Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
|
||||
setPlugins(*properties("platformPlugins").split(',').map(String::trim).filter(String::isNotEmpty).toTypedArray())
|
||||
plugins.set(properties("platformPlugins").split(',').map(String::trim).filter(String::isNotEmpty))
|
||||
}
|
||||
|
||||
// Configure gradle-changelog-plugin plugin.
|
||||
@ -80,43 +78,37 @@ tasks {
|
||||
}
|
||||
|
||||
patchPluginXml {
|
||||
version(properties("pluginVersion"))
|
||||
sinceBuild(properties("pluginSinceBuild"))
|
||||
untilBuild(properties("pluginUntilBuild"))
|
||||
version.set(properties("pluginVersion"))
|
||||
sinceBuild.set(properties("pluginSinceBuild"))
|
||||
untilBuild.set(properties("pluginUntilBuild"))
|
||||
|
||||
// Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
|
||||
pluginDescription(
|
||||
closure {
|
||||
File("./README.md").readText().lines().run {
|
||||
val start = "<!-- Plugin description -->"
|
||||
val end = "<!-- Plugin description end -->"
|
||||
pluginDescription.set(
|
||||
File(projectDir, "README.md").readText().lines().run {
|
||||
val start = "<!-- Plugin description -->"
|
||||
val end = "<!-- Plugin description end -->"
|
||||
|
||||
if (!containsAll(listOf(start, end))) {
|
||||
throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
|
||||
}
|
||||
subList(indexOf(start) + 1, indexOf(end))
|
||||
}.joinToString("\n").run { markdownToHTML(this) }
|
||||
}
|
||||
if (!containsAll(listOf(start, end))) {
|
||||
throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
|
||||
}
|
||||
subList(indexOf(start) + 1, indexOf(end))
|
||||
}.joinToString("\n").run { markdownToHTML(this) }
|
||||
)
|
||||
|
||||
// Get the latest available change notes from the changelog file
|
||||
changeNotes(
|
||||
closure {
|
||||
changelog.getLatest().toHTML()
|
||||
}
|
||||
)
|
||||
changeNotes.set(provider { changelog.getLatest().toHTML() })
|
||||
}
|
||||
|
||||
runPluginVerifier {
|
||||
ideVersions(properties("pluginVerifierIdeVersions"))
|
||||
ideVersions.set(properties("pluginVerifierIdeVersions").split(',').map(String::trim).filter(String::isNotEmpty))
|
||||
}
|
||||
|
||||
publishPlugin {
|
||||
dependsOn("patchChangelog")
|
||||
token(System.getenv("PUBLISH_TOKEN"))
|
||||
token.set(System.getenv("PUBLISH_TOKEN"))
|
||||
// pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
|
||||
// Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
|
||||
// https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
|
||||
channels(properties("pluginVersion").split('-').getOrElse(1) { "default" }.split('.').first())
|
||||
channels.set(listOf(properties("pluginVersion").split('-').getOrElse(1) { "default" }.split('.').first()))
|
||||
}
|
||||
}
|
||||
|
26
example/json/locale-de.json
Normal file
26
example/json/locale-de.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"alpha": {
|
||||
"first": "Beispiel Übersetzung",
|
||||
"second": "Andere Übersetzung"
|
||||
},
|
||||
"beta": {
|
||||
"title": "Ein Titel",
|
||||
"nested": {
|
||||
"title": "Ein verschachtelter Titel"
|
||||
}
|
||||
},
|
||||
"gamma": {
|
||||
"title": "Gamma Titel",
|
||||
"array": {
|
||||
"simple": [
|
||||
"Erstes Element",
|
||||
"Zweites Element"
|
||||
],
|
||||
"escaped": [
|
||||
"Erstes;Element",
|
||||
"Zweites Element",
|
||||
"Drittes;Element"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
26
example/json/locale-en.json
Normal file
26
example/json/locale-en.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"alpha": {
|
||||
"first": "example translation",
|
||||
"second": "another translation"
|
||||
},
|
||||
"beta": {
|
||||
"title": "some title",
|
||||
"nested": {
|
||||
"title": "some nested title"
|
||||
}
|
||||
},
|
||||
"gamma": {
|
||||
"title": "gamma title",
|
||||
"array": {
|
||||
"simple": [
|
||||
"first element",
|
||||
"second element"
|
||||
],
|
||||
"escaped": [
|
||||
"first;element",
|
||||
"second element",
|
||||
"third;element"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
5
example/modularized-json/locale-de/account.json
Normal file
5
example/modularized-json/locale-de/account.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"subscription": "Abonnement",
|
||||
"support": "Unterstützung",
|
||||
"delete": "Löschen"
|
||||
}
|
10
example/modularized-json/locale-de/auth.json
Normal file
10
example/modularized-json/locale-de/auth.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": [
|
||||
"Ein",
|
||||
"array",
|
||||
"Titel"
|
||||
],
|
||||
"login": "Einloggen",
|
||||
"logout": "Ausloggen",
|
||||
"register": "Registrieren"
|
||||
}
|
10
example/modularized-json/locale-de/user.json
Normal file
10
example/modularized-json/locale-de/user.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"username": "Benutzername",
|
||||
"email": "Email-Adresse",
|
||||
"address": {
|
||||
"zip": "Postleitzahl",
|
||||
"city": "Ort",
|
||||
"street": "Straße",
|
||||
"number": "Hausnummer"
|
||||
}
|
||||
}
|
5
example/modularized-json/locale-en/account.json
Normal file
5
example/modularized-json/locale-en/account.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"subscription": "Subscription",
|
||||
"support": "Support",
|
||||
"delete": "Delete"
|
||||
}
|
10
example/modularized-json/locale-en/auth.json
Normal file
10
example/modularized-json/locale-en/auth.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": [
|
||||
"Some",
|
||||
"array",
|
||||
"title"
|
||||
],
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
"register": "Register"
|
||||
}
|
10
example/modularized-json/locale-en/user.json
Normal file
10
example/modularized-json/locale-en/user.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"username": "Username",
|
||||
"email": "Email Address",
|
||||
"address": {
|
||||
"zip": "ZIP code",
|
||||
"city": "City",
|
||||
"street": "Street",
|
||||
"number": "House number"
|
||||
}
|
||||
}
|
6
example/resource-bundle/locale_de.properties
Normal file
6
example/resource-bundle/locale_de.properties
Normal file
@ -0,0 +1,6 @@
|
||||
account.subscription=Abonnement
|
||||
auth.login=Einloggen
|
||||
auth.logout=Ausloggen
|
||||
auth.register=Registrieren
|
||||
user.email=Email-Adresse
|
||||
user.username=Benutzername
|
6
example/resource-bundle/locale_en.properties
Normal file
6
example/resource-bundle/locale_en.properties
Normal file
@ -0,0 +1,6 @@
|
||||
account.subscription=Subscription
|
||||
auth.login=Login
|
||||
auth.logout=Logout
|
||||
auth.register=Register
|
||||
user.email=Email Address
|
||||
user.username=Username
|
@ -3,19 +3,19 @@
|
||||
|
||||
pluginGroup = de.marhali.easyi18n
|
||||
pluginName = easy-i18n
|
||||
pluginVersion = 1.3.0
|
||||
pluginVersion = 1.4.0
|
||||
pluginSinceBuild = 202
|
||||
pluginUntilBuild = 211.*
|
||||
# Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
|
||||
# See https://jb.gg/intellij-platform-builds-list for available build versions
|
||||
pluginVerifierIdeVersions = 2020.2.4, 2020.3.2, 2021.1
|
||||
pluginVerifierIdeVersions = 2020.2.4, 2020.3.4, 2021.1.1
|
||||
|
||||
platformType = IC
|
||||
platformVersion = 2021.1
|
||||
platformVersion = 2021.1.3
|
||||
platformDownloadSources = true
|
||||
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
|
||||
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
|
||||
platformPlugins =
|
||||
platformPlugins = org.jetbrains.kotlin
|
||||
|
||||
# Opt-out flag for bundling Kotlin standard library.
|
||||
# See https://kotlinlang.org/docs/reference/using-gradle.html#dependency-on-the-standard-library for details.
|
||||
|
@ -9,9 +9,9 @@ import com.intellij.ui.content.ContentFactory;
|
||||
|
||||
import de.marhali.easyi18n.service.DataStore;
|
||||
import de.marhali.easyi18n.service.WindowManager;
|
||||
import de.marhali.easyi18n.ui.action.*;
|
||||
import de.marhali.easyi18n.ui.tabs.TableView;
|
||||
import de.marhali.easyi18n.ui.tabs.TreeView;
|
||||
import de.marhali.easyi18n.action.*;
|
||||
import de.marhali.easyi18n.tabs.TableView;
|
||||
import de.marhali.easyi18n.tabs.TreeView;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
package de.marhali.easyi18n.ui.action;
|
||||
package de.marhali.easyi18n.action;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
|
||||
import de.marhali.easyi18n.service.WindowManager;
|
||||
import de.marhali.easyi18n.ui.dialog.AddDialog;
|
||||
import de.marhali.easyi18n.dialog.AddDialog;
|
||||
import de.marhali.easyi18n.util.TreeUtil;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.action;
|
||||
package de.marhali.easyi18n.action;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.action;
|
||||
package de.marhali.easyi18n.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
@ -1,9 +1,9 @@
|
||||
package de.marhali.easyi18n.ui.action;
|
||||
package de.marhali.easyi18n.action;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import de.marhali.easyi18n.ui.dialog.SettingsDialog;
|
||||
import de.marhali.easyi18n.dialog.SettingsDialog;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ResourceBundle;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.action.treeview;
|
||||
package de.marhali.easyi18n.action.treeview;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.action.treeview;
|
||||
package de.marhali.easyi18n.action.treeview;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.dialog;
|
||||
package de.marhali.easyi18n.dialog;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.dialog;
|
||||
package de.marhali.easyi18n.dialog;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
@ -10,7 +10,7 @@ import de.marhali.easyi18n.service.DataStore;
|
||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
||||
import de.marhali.easyi18n.model.TranslationDelete;
|
||||
import de.marhali.easyi18n.model.TranslationUpdate;
|
||||
import de.marhali.easyi18n.ui.dialog.descriptor.DeleteActionDescriptor;
|
||||
import de.marhali.easyi18n.dialog.descriptor.DeleteActionDescriptor;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EtchedBorder;
|
@ -1,10 +1,11 @@
|
||||
package de.marhali.easyi18n.ui.dialog;
|
||||
package de.marhali.easyi18n.dialog;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
|
||||
@ -26,6 +27,7 @@ public class SettingsDialog {
|
||||
private TextFieldWithBrowseButton pathText;
|
||||
private JBTextField filePatternText;
|
||||
private JBTextField previewText;
|
||||
private JBCheckBox codeAssistanceCheckbox;
|
||||
|
||||
public SettingsDialog(Project project) {
|
||||
this.project = project;
|
||||
@ -35,18 +37,20 @@ public class SettingsDialog {
|
||||
String localesPath = SettingsService.getInstance(project).getState().getLocalesPath();
|
||||
String filePattern = SettingsService.getInstance(project).getState().getFilePattern();
|
||||
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
||||
boolean codeAssistance = SettingsService.getInstance(project).getState().isCodeAssistance();
|
||||
|
||||
if(prepare(localesPath, filePattern, previewLocale).show() == DialogWrapper.OK_EXIT_CODE) { // Save changes
|
||||
if(prepare(localesPath, filePattern, previewLocale, codeAssistance).show() == DialogWrapper.OK_EXIT_CODE) { // Save changes
|
||||
SettingsService.getInstance(project).getState().setLocalesPath(pathText.getText());
|
||||
SettingsService.getInstance(project).getState().setFilePattern(filePatternText.getText());
|
||||
SettingsService.getInstance(project).getState().setPreviewLocale(previewText.getText());
|
||||
SettingsService.getInstance(project).getState().setCodeAssistance(codeAssistanceCheckbox.isSelected());
|
||||
|
||||
// Reload instance
|
||||
DataStore.getInstance(project).reloadFromDisk();
|
||||
}
|
||||
}
|
||||
|
||||
private DialogBuilder prepare(String localesPath, String filePattern, String previewLocale) {
|
||||
private DialogBuilder prepare(String localesPath, String filePattern, String previewLocale, boolean codeAssistance) {
|
||||
JPanel rootPanel = new JPanel(new GridLayout(0, 1, 2, 2));
|
||||
|
||||
JBLabel pathLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("settings.path.text"));
|
||||
@ -73,6 +77,11 @@ public class SettingsDialog {
|
||||
rootPanel.add(previewLabel);
|
||||
rootPanel.add(previewText);
|
||||
|
||||
codeAssistanceCheckbox = new JBCheckBox(ResourceBundle.getBundle("messages").getString("settings.editor.assistance"));
|
||||
codeAssistanceCheckbox.setSelected(codeAssistance);
|
||||
|
||||
rootPanel.add(codeAssistanceCheckbox);
|
||||
|
||||
DialogBuilder builder = new DialogBuilder();
|
||||
builder.setTitle(ResourceBundle.getBundle("messages").getString("action.settings"));
|
||||
builder.removeAllActions();
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.dialog.descriptor;
|
||||
package de.marhali.easyi18n.dialog.descriptor;
|
||||
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
@ -1,11 +1,8 @@
|
||||
package de.marhali.easyi18n.ui.editor;
|
||||
package de.marhali.easyi18n.editor;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLiteralValue;
|
||||
|
||||
import de.marhali.easyi18n.model.LocalizedNode;
|
||||
import de.marhali.easyi18n.service.DataStore;
|
||||
@ -14,28 +11,25 @@ import de.marhali.easyi18n.service.SettingsService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Translation key annotator.
|
||||
* Superclass for managing key annotations.
|
||||
* @author marhali
|
||||
*/
|
||||
public class I18nKeyAnnotator implements Annotator {
|
||||
public class KeyAnnotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if(!(element instanceof PsiLiteralValue)) {
|
||||
/**
|
||||
* Adds annotations for i18n keys with content preview for preferred locale.
|
||||
* @param key I18n key extracted by psi element
|
||||
* @param project Project instance
|
||||
* @param holder Annotation holder
|
||||
*/
|
||||
protected void annotate(@NotNull String key, @NotNull Project project, @NotNull AnnotationHolder holder) {
|
||||
// Do not annotate keys if service is disabled
|
||||
if(!SettingsService.getInstance(project).getState().isCodeAssistance()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiLiteralValue literalValue = (PsiLiteralValue) element;
|
||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
||||
|
||||
if(value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Project project = element.getProject();
|
||||
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
||||
|
||||
LocalizedNode node = DataStore.getInstance(project).getTranslations().getNode(value);
|
||||
LocalizedNode node = DataStore.getInstance(project).getTranslations().getNode(key);
|
||||
|
||||
if(node == null) { // Unknown translation. Just ignore it
|
||||
return;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.editor;
|
||||
package de.marhali.easyi18n.editor;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
@ -20,11 +20,19 @@ import java.util.List;
|
||||
* I18n translation key completion provider.
|
||||
* @author marhali
|
||||
*/
|
||||
public class I18nCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
public class KeyCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
@NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
|
||||
Project project = parameters.getOriginalFile().getProject();
|
||||
|
||||
// Do not annotate keys if service is disabled
|
||||
if(!SettingsService.getInstance(project).getState().isCodeAssistance()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
||||
|
||||
String query = result.getPrefixMatcher().getPrefix();
|
@ -0,0 +1,33 @@
|
||||
package de.marhali.easyi18n.editor.generic;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLiteralValue;
|
||||
|
||||
import de.marhali.easyi18n.editor.KeyAnnotator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Translation key annotator for generic languages which support {@link PsiLiteralValue}.
|
||||
* @author marhali
|
||||
*/
|
||||
public class GenericKeyAnnotator extends KeyAnnotator implements Annotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if(!(element instanceof PsiLiteralValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiLiteralValue literalValue = (PsiLiteralValue) element;
|
||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
||||
|
||||
if(value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
annotate(value, element.getProject(), holder);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package de.marhali.easyi18n.editor.generic;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.patterns.*;
|
||||
import com.intellij.psi.PsiLiteralValue;
|
||||
import de.marhali.easyi18n.editor.KeyCompletionProvider;
|
||||
|
||||
/**
|
||||
* Translation key completion for generic languages which support {@link PsiLiteralValue}.
|
||||
* @author marhali
|
||||
*/
|
||||
public class GenericKeyCompletionContributor extends CompletionContributor {
|
||||
|
||||
public GenericKeyCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(PsiLiteralValue.class),
|
||||
new KeyCompletionProvider());
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package de.marhali.easyi18n.editor.kotlin;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
import de.marhali.easyi18n.editor.KeyAnnotator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
||||
|
||||
/**
|
||||
* Kotlin specific translation key annotator
|
||||
* @author marhali
|
||||
*/
|
||||
public class KotlinKeyAnnotator extends KeyAnnotator implements Annotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if(!(element instanceof KtLiteralStringTemplateEntry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String value = element.getText();
|
||||
|
||||
if(value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
annotate(value, element.getProject(), holder);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package de.marhali.easyi18n.editor.kotlin;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
|
||||
import de.marhali.easyi18n.editor.KeyCompletionProvider;
|
||||
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
||||
|
||||
/**
|
||||
* Kotlin specific translation key completion contributor.
|
||||
* @author marhali
|
||||
*/
|
||||
public class KotlinKeyCompletionContributor extends CompletionContributor {
|
||||
|
||||
public KotlinKeyCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(KtLiteralStringTemplateEntry.class),
|
||||
new KeyCompletionProvider());
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.listener;
|
||||
package de.marhali.easyi18n.listener;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.listener;
|
||||
package de.marhali.easyi18n.listener;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
@ -11,10 +11,12 @@ public class SettingsState {
|
||||
|
||||
public static final String DEFAULT_PREVIEW_LOCALE = "en";
|
||||
public static final String DEFAULT_FILE_PATTERN = ".*";
|
||||
public static final boolean DEFAULT_CODE_ASSISTANCE = true;
|
||||
|
||||
private String localesPath;
|
||||
private String filePattern;
|
||||
private String previewLocale;
|
||||
private Boolean codeAssistance;
|
||||
|
||||
public SettingsState() {}
|
||||
|
||||
@ -41,4 +43,12 @@ public class SettingsState {
|
||||
public void setPreviewLocale(String previewLocale) {
|
||||
this.previewLocale = previewLocale;
|
||||
}
|
||||
|
||||
public boolean isCodeAssistance() {
|
||||
return codeAssistance == null ? DEFAULT_CODE_ASSISTANCE : codeAssistance;
|
||||
}
|
||||
|
||||
public void setCodeAssistance(boolean codeAssistance) {
|
||||
this.codeAssistance = codeAssistance;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.renderer;
|
||||
package de.marhali.easyi18n.renderer;
|
||||
|
||||
import com.intellij.ui.JBColor;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.renderer;
|
||||
package de.marhali.easyi18n.renderer;
|
||||
|
||||
import com.intellij.ide.util.treeView.NodeRenderer;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
@ -7,9 +7,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Similar to {@link NodeRenderer} but will will override {@link #getPresentation(Object)} to
|
@ -2,8 +2,8 @@ package de.marhali.easyi18n.service;
|
||||
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
|
||||
import de.marhali.easyi18n.ui.tabs.TableView;
|
||||
import de.marhali.easyi18n.ui.tabs.TreeView;
|
||||
import de.marhali.easyi18n.tabs.TableView;
|
||||
import de.marhali.easyi18n.tabs.TreeView;
|
||||
|
||||
public class WindowManager {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.marhali.easyi18n.ui.tabs.TableView">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.marhali.easyi18n.tabs.TableView">
|
||||
<grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.tabs;
|
||||
package de.marhali.easyi18n.tabs;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
@ -11,10 +11,10 @@ import de.marhali.easyi18n.model.Translations;
|
||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
||||
import de.marhali.easyi18n.model.TranslationDelete;
|
||||
import de.marhali.easyi18n.model.table.TableModelTranslator;
|
||||
import de.marhali.easyi18n.ui.dialog.EditDialog;
|
||||
import de.marhali.easyi18n.ui.listener.DeleteKeyListener;
|
||||
import de.marhali.easyi18n.ui.listener.PopupClickListener;
|
||||
import de.marhali.easyi18n.ui.renderer.TableRenderer;
|
||||
import de.marhali.easyi18n.dialog.EditDialog;
|
||||
import de.marhali.easyi18n.listener.DeleteKeyListener;
|
||||
import de.marhali.easyi18n.listener.PopupClickListener;
|
||||
import de.marhali.easyi18n.renderer.TableRenderer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.marhali.easyi18n.ui.tabs.TreeView">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.marhali.easyi18n.tabs.TreeView">
|
||||
<grid id="27dc6" binding="rootPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
@ -1,4 +1,4 @@
|
||||
package de.marhali.easyi18n.ui.tabs;
|
||||
package de.marhali.easyi18n.tabs;
|
||||
|
||||
import com.intellij.ide.projectView.PresentationData;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
@ -14,13 +14,12 @@ import de.marhali.easyi18n.model.Translations;
|
||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
||||
import de.marhali.easyi18n.model.TranslationDelete;
|
||||
import de.marhali.easyi18n.model.tree.TreeModelTranslator;
|
||||
import de.marhali.easyi18n.ui.action.treeview.CollapseTreeViewAction;
|
||||
import de.marhali.easyi18n.ui.action.treeview.ExpandTreeViewAction;
|
||||
import de.marhali.easyi18n.ui.dialog.EditDialog;
|
||||
import de.marhali.easyi18n.ui.listener.DeleteKeyListener;
|
||||
import de.marhali.easyi18n.ui.listener.PopupClickListener;
|
||||
import de.marhali.easyi18n.ui.renderer.TreeRenderer;
|
||||
import de.marhali.easyi18n.util.TranslationsUtil;
|
||||
import de.marhali.easyi18n.action.treeview.CollapseTreeViewAction;
|
||||
import de.marhali.easyi18n.action.treeview.ExpandTreeViewAction;
|
||||
import de.marhali.easyi18n.dialog.EditDialog;
|
||||
import de.marhali.easyi18n.listener.DeleteKeyListener;
|
||||
import de.marhali.easyi18n.listener.PopupClickListener;
|
||||
import de.marhali.easyi18n.renderer.TreeRenderer;
|
||||
import de.marhali.easyi18n.util.TreeUtil;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
@ -1,18 +0,0 @@
|
||||
package de.marhali.easyi18n.ui.editor;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.patterns.*;
|
||||
import com.intellij.psi.PsiLiteralValue;
|
||||
|
||||
/**
|
||||
* Show i18n key completion for literal values.
|
||||
* @author marhali
|
||||
*/
|
||||
public class I18nCompletionContributor extends CompletionContributor {
|
||||
|
||||
public I18nCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(PsiLiteralValue.class),
|
||||
new I18nCompletionProvider());
|
||||
}
|
||||
}
|
51
src/main/java/de/marhali/easyi18n/util/JsonArrayUtil.java
Normal file
51
src/main/java/de/marhali/easyi18n/util/JsonArrayUtil.java
Normal file
@ -0,0 +1,51 @@
|
||||
package de.marhali.easyi18n.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility methods to read and write json arrays.
|
||||
* @author marhali
|
||||
*/
|
||||
public class JsonArrayUtil {
|
||||
|
||||
public static String ARRAY_PREFIX = "!arr[";
|
||||
public static String ARRAY_SUFFIX = "]";
|
||||
public static char ARRAY_DELIMITER = ';';
|
||||
|
||||
public static String read(JsonArray array) {
|
||||
StringBuilder builder = new StringBuilder(ARRAY_PREFIX);
|
||||
|
||||
for(int i = 0; i < array.size(); i++) {
|
||||
if(i > 0) {
|
||||
builder.append(ARRAY_DELIMITER);
|
||||
}
|
||||
|
||||
String value = array.get(i).getAsString().replace(";", "\\;");
|
||||
builder.append(StringUtil.escapeControls(value, true));
|
||||
}
|
||||
|
||||
builder.append(ARRAY_SUFFIX);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static JsonArray write(String concat) {
|
||||
concat = concat.substring(ARRAY_PREFIX.length(), concat.length() - ARRAY_SUFFIX.length());
|
||||
String regex = "(?<!\\\\)" + Pattern.quote(String.valueOf(ARRAY_DELIMITER));
|
||||
|
||||
JsonArray array = new JsonArray();
|
||||
|
||||
for(String element : concat.split(regex)) {
|
||||
element = element.replace("\\" + ARRAY_DELIMITER, String.valueOf(ARRAY_DELIMITER));
|
||||
array.add(StringEscapeUtils.unescapeJava(element));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static boolean isArray(String concat) {
|
||||
return concat != null && concat.startsWith(ARRAY_PREFIX) && concat.endsWith(ARRAY_SUFFIX);
|
||||
}
|
||||
}
|
@ -27,8 +27,13 @@ public class JsonUtil {
|
||||
public static void writeTree(String locale, JsonObject parent, LocalizedNode node) {
|
||||
if(node.isLeaf() && !node.getKey().equals(LocalizedNode.ROOT_KEY)) {
|
||||
if(node.getValue().get(locale) != null) {
|
||||
String value = StringEscapeUtils.unescapeJava(node.getValue().get(locale));
|
||||
parent.add(node.getKey(), new JsonPrimitive(value));
|
||||
|
||||
if(JsonArrayUtil.isArray(node.getValue().get(locale))) {
|
||||
parent.add(node.getKey(), JsonArrayUtil.write(node.getValue().get(locale)));
|
||||
} else {
|
||||
String value = StringEscapeUtils.unescapeJava(node.getValue().get(locale));
|
||||
parent.add(node.getKey(), new JsonPrimitive(value));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -78,7 +83,11 @@ public class JsonUtil {
|
||||
}
|
||||
|
||||
Map<String, String> messages = leafNode.getValue();
|
||||
String value = StringUtil.escapeControls(entry.getValue().getAsString(), true);
|
||||
|
||||
String value = entry.getValue().isJsonArray()
|
||||
? JsonArrayUtil.read(entry.getValue().getAsJsonArray())
|
||||
: StringUtil.escapeControls(entry.getValue().getAsString(), true);
|
||||
|
||||
messages.put(locale, value);
|
||||
leafNode.setValue(messages);
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<annotator language="kotlin" implementationClass="de.marhali.easyi18n.editor.kotlin.KotlinKeyAnnotator" />
|
||||
|
||||
<completion.contributor language="kotlin"
|
||||
implementationClass="de.marhali.easyi18n.editor.kotlin.KotlinKeyCompletionContributor" />
|
||||
</extensions>
|
||||
</idea-plugin>
|
@ -5,15 +5,17 @@
|
||||
|
||||
<!-- Product and plugin compatibility requirements -->
|
||||
<!-- https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
<depends optional="true" config-file="de.marhali.easyi18n-kotlin.xml">org.jetbrains.kotlin</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<toolWindow id="Easy I18n" anchor="bottom" factoryClass="de.marhali.easyi18n.TranslatorToolWindowFactory" />
|
||||
<projectService serviceImplementation="de.marhali.easyi18n.service.SettingsService" />
|
||||
|
||||
<completion.contributor language="any"
|
||||
implementationClass="de.marhali.easyi18n.ui.editor.I18nCompletionContributor" />
|
||||
implementationClass="de.marhali.easyi18n.editor.generic.GenericKeyCompletionContributor" />
|
||||
|
||||
<annotator language="" implementationClass="de.marhali.easyi18n.ui.editor.I18nKeyAnnotator" />
|
||||
<annotator language="" implementationClass="de.marhali.easyi18n.editor.generic.GenericKeyAnnotator" />
|
||||
</extensions>
|
||||
</idea-plugin>
|
@ -14,4 +14,5 @@ translation.locales=Locales
|
||||
settings.path.title=Locales Directory
|
||||
settings.path.text=Locales directory
|
||||
settings.path.file-pattern=Translation file pattern
|
||||
settings.preview=Preview locale
|
||||
settings.preview=Preview locale
|
||||
settings.editor.assistance=I18n key completion and annotation inside editor
|
Loading…
x
Reference in New Issue
Block a user