├── .gitignore
├── README.md
├── build.gradle
├── gradlew
├── gradlew.bat
├── screenshots
└── howUse.gif
├── settings.gradle
├── src
└── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── wujs
│ │ ├── action
│ │ └── AndroidLocalization.java
│ │ ├── data
│ │ ├── Key.java
│ │ ├── Log.java
│ │ ├── SerializeUtil.java
│ │ ├── StorageDataKey.java
│ │ └── task
│ │ │ └── GetTranslationTask.java
│ │ ├── language_engine
│ │ ├── HttpUtils.java
│ │ ├── TranslationEngineType.java
│ │ ├── baidu
│ │ │ ├── BaiduTranslationApi.java
│ │ │ ├── HttpGet.java
│ │ │ └── MD5.java
│ │ ├── bing
│ │ │ ├── BingResultParser.java
│ │ │ ├── BingTranslationApi.java
│ │ │ └── TranslateArrayResponse.java
│ │ └── google
│ │ │ ├── GoogleTranslationApi.java
│ │ │ └── GoogleTranslationer.java
│ │ ├── module
│ │ ├── AndroidString.java
│ │ ├── FilterRule.java
│ │ └── SupportedLanguages.java
│ │ ├── settings
│ │ └── SettingConfigurable.java
│ │ ├── ui
│ │ ├── AddFilterRuleDialog.java
│ │ ├── GoogleAlertDialog.java
│ │ └── MultiSelectDialog.java
│ │ └── util
│ │ └── Logger.java
│ └── resources
│ ├── META-INF
│ └── plugin.xml
│ └── icons
│ ├── globe.png
│ └── globe@2x.png
└── values
└── strings.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### gradle_project template
3 | .idea
4 | *.iml
5 | build
6 | .gradle
7 | gradle
8 | out
9 | gen
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # An important plugin for android developer working on Google play
2 |
3 | ##### [Instructions for usage from westlinkin](https://github.com/westlinkin/AndroidLocalizationer/blob/master/README.md)
4 |
5 | ##### [中文教程](http://blog.csdn.net/wjskeepmaking/article/details/78817915)
6 |
7 | ### ChangeLog
8 |
9 | #### version 1.0.0
10 |
11 | * Compatible with Android Studio 4.1
12 |
13 | #### version 0.0.1
14 |
15 | * Add Baidu Translation as default Translator.[Click here](http://api.fanyi.baidu.com/api/trans/product/index) to apply one for free.
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'org.jetbrains.intellij' version '0.5.0'
4 | }
5 |
6 | group 'org.example.wujushan'
7 | version '1.0.0'
8 | sourceCompatibility = 1.8
9 |
10 | repositories {
11 | mavenCentral()
12 | }
13 |
14 | dependencies {
15 | testCompile group: 'junit', name: 'junit', version: '4.12'
16 | }
17 |
18 | // See https://github.com/JetBrains/gradle-intellij-plugin/
19 | intellij {
20 | version '2020.1.2'
21 | pluginName = 'AndroidLocalizationer'
22 | }
23 |
24 | tasks.withType(JavaCompile) {
25 | options.encoding = "UTF-8"
26 | }
27 |
28 | patchPluginXml {
29 | changeNotes """
30 | Version 1.0.0
31 | Compatible with Android Studio 4.1
32 | """
33 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 |
88 | @rem Execute Gradle
89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
90 |
91 | :end
92 | @rem End local scope for the variables with windows NT shell
93 | if "%ERRORLEVEL%"=="0" goto mainEnd
94 |
95 | :fail
96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
97 | rem the _cmd.exe /c_ return code!
98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
99 | exit /b 1
100 |
101 | :mainEnd
102 | if "%OS%"=="Windows_NT" endlocal
103 |
104 | :omega
105 |
--------------------------------------------------------------------------------
/screenshots/howUse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wujushan/AndroidLocalizationer/ba646217218c2209aab437961f672bc503215e94/screenshots/howUse.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'AndroidLocalizationer'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/action/AndroidLocalization.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.action;
18 |
19 | import com.example.wujs.data.Log;
20 | import com.example.wujs.data.StorageDataKey;
21 | import com.example.wujs.data.task.GetTranslationTask;
22 | import com.example.wujs.language_engine.TranslationEngineType;
23 | import com.example.wujs.module.AndroidString;
24 | import com.example.wujs.module.SupportedLanguages;
25 | import com.example.wujs.ui.MultiSelectDialog;
26 | import com.example.wujs.util.Logger;
27 | import com.intellij.ide.util.PropertiesComponent;
28 | import com.intellij.openapi.actionSystem.AnAction;
29 | import com.intellij.openapi.actionSystem.AnActionEvent;
30 | import com.intellij.openapi.actionSystem.CommonDataKeys;
31 | import com.intellij.openapi.project.Project;
32 | import com.intellij.openapi.ui.Messages;
33 | import com.intellij.openapi.util.IconLoader;
34 | import com.intellij.openapi.vfs.VirtualFile;
35 | import org.jetbrains.annotations.Nullable;
36 |
37 | import java.io.IOException;
38 | import java.util.List;
39 |
40 | /**
41 | * Created by Wesley Lin on 11/26/14.
42 | */
43 | public class AndroidLocalization extends AnAction implements MultiSelectDialog.OnOKClickedListener {
44 |
45 | private static final String LOCALIZATION_TITLE = "Choose alternative string resources";
46 | private static final String LOCALIZATION_MSG = "Warning: " +
47 | "The string resources are translated by %s, " +
48 | "try keeping your string resources simple, so that the result is more satisfied.";
49 | private static final String OVERRIDE_EXITS_STRINGS = "Override the existing strings";
50 |
51 | private Project project;
52 | private List androidStringsInStringFile = null;
53 |
54 | public TranslationEngineType defaultTranslationEngine = TranslationEngineType.Baidu;
55 |
56 | private VirtualFile clickedFile;
57 |
58 | public AndroidLocalization() {
59 | super("Convert to other languages", null, IconLoader.getIcon("/icons/globe.png"));
60 |
61 | }
62 |
63 | @Override
64 | public void update(AnActionEvent e) {
65 | final VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
66 |
67 | boolean isStringXML = isStringXML(file);
68 | e.getPresentation().setEnabled(isStringXML);
69 | e.getPresentation().setVisible(isStringXML);
70 | }
71 |
72 |
73 | @Override
74 | public void actionPerformed(AnActionEvent e) {
75 | project = CommonDataKeys.PROJECT.getData(e.getDataContext());
76 | Logger.init(getClass().getSimpleName(), Logger.DEBUG);
77 | if (project == null) {
78 | return;
79 | }
80 |
81 | clickedFile = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
82 | Log.i("clicked file: " + clickedFile.getPath());
83 |
84 | if (PropertiesComponent.getInstance().isValueSet(StorageDataKey.SettingLanguageEngine)) {
85 | defaultTranslationEngine = TranslationEngineType.fromName(
86 | PropertiesComponent.getInstance().getValue(StorageDataKey.SettingLanguageEngine));
87 | }
88 |
89 | try {
90 | // androidStringsInStringFile = AndroidString.getAndroidStringsList(clickedFile.contentsToByteArray());
91 | androidStringsInStringFile = AndroidString.getAndroidStrings(clickedFile.getInputStream());
92 | } catch (IOException e1) {
93 | e1.printStackTrace();
94 | }
95 |
96 |
97 | if (androidStringsInStringFile == null || androidStringsInStringFile.isEmpty()) {
98 | showErrorDialog(project, "Target file does not contain any strings or is not valid xml file.");
99 | return;
100 | }
101 |
102 | // show dialog
103 | MultiSelectDialog multiSelectDialog = new MultiSelectDialog(project,
104 | String.format(LOCALIZATION_MSG, defaultTranslationEngine.getDisplayName()),
105 | LOCALIZATION_TITLE,
106 | OVERRIDE_EXITS_STRINGS,
107 | PropertiesComponent.getInstance(project).getBoolean(StorageDataKey.OverrideCheckBoxStatus, false),
108 | defaultTranslationEngine,
109 | false);
110 | multiSelectDialog.setOnOKClickedListener(this);
111 | multiSelectDialog.show();
112 | }
113 |
114 | @Override
115 | public void onClick(List selectedLanguages, boolean overrideChecked) {
116 | // set consistence data
117 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(project);
118 | propertiesComponent.setValue(StorageDataKey.OverrideCheckBoxStatus, String.valueOf(overrideChecked));
119 |
120 | List allData = SupportedLanguages.getAllSupportedLanguages(defaultTranslationEngine);
121 |
122 | for (SupportedLanguages language : allData) {
123 | propertiesComponent.setValue(StorageDataKey.SupportedLanguageCheckStatusPrefix + language.getLanguageCode(),
124 | String.valueOf(selectedLanguages.contains(language)));
125 | }
126 |
127 | new GetTranslationTask(project, "Translation in progress, using " + defaultTranslationEngine.getDisplayName(),
128 | selectedLanguages, androidStringsInStringFile, defaultTranslationEngine, overrideChecked, clickedFile)
129 | .setCancelText("Translation has been canceled").queue();
130 | }
131 |
132 | public static void showErrorDialog(Project project, String msg) {
133 | Messages.showErrorDialog(project, msg, "Error");
134 | }
135 |
136 | public static void showSuccessDialog(Project project, String msg) {
137 | Messages.showMessageDialog(project, msg, "Success", null);
138 | }
139 |
140 | private static boolean isStringXML(@Nullable VirtualFile file) {
141 | if (file == null)
142 | return false;
143 |
144 | if (!file.getName().equals("strings.xml"))
145 | return false;
146 |
147 | if (file.getParent() == null)
148 | return false;
149 |
150 | /* // only show popup menu for English strings
151 |
152 | if (!file.getParent().getName().equals("values") && !file.getParent().getName().startsWith("values-en"))
153 | return false;*/
154 |
155 | return true;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/data/Key.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.data;
18 |
19 | /**
20 | * Created by Wesley Lin on 11/29/14.
21 | */
22 | public class Key {
23 |
24 | // bing, clientId and clientSecret can be set by users
25 | public static final String BING_CLIENT_ID = "android_localizationer";
26 |
27 | public static final String BING_CLIENT_SECRET = "eQiD1XOQCKToGLWMl0GXuWZb2cQJqYIwid8UPhln5CY=";
28 | public static final String BING_CLIENT_SCOPE = "http://api.microsofttranslator.com";
29 | public static final String BING_CLIENT_GRANT_TYPE = "client_credentials";
30 |
31 | public static final String BAIDU_CLIENT_ID = "";
32 | public static final String BAIDU_CLIENT_SECRET = "";
33 |
34 | // other than api keys
35 | public static final String NO_NEED_TRANSLATION_ANDROID_STRING_PREFIX = "NAL_";
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/data/Log.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.data;
18 |
19 | /**
20 | * Created by Wesley Lin on 12/3/14.
21 | */
22 | public class Log {
23 | public static void i(String... params) {
24 | if (params == null)
25 | return;
26 | String out = "";
27 | for (int i = 0; i < params.length; i++) {
28 | out += params[i] + "\n";
29 | }
30 | System.out.println(out);
31 | }
32 |
33 | public static void i(Object... params) {
34 | if (params == null)
35 | return;
36 | String out = "";
37 | for (int i = 0; i < params.length; i++) {
38 | out += params[i].toString() + "\n";
39 | }
40 | System.out.println(out);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/data/SerializeUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.data;
18 |
19 |
20 | import com.example.wujs.module.FilterRule;
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | /**
25 | * Created by Wesley Lin on 12/17/14.
26 | */
27 | public class SerializeUtil {
28 |
29 | public static String serializeFilterRuleList(List rules) {
30 | StringBuilder sb = new StringBuilder();
31 | for (int i = 0; i < rules.size(); i++) {
32 | if (i != 0)
33 | sb.append("\n");
34 |
35 | sb.append(rules.get(i).getFilterRuleType().toName())
36 | .append("<>")
37 | .append(rules.get(i).getFilterString());
38 | }
39 | return sb.toString();
40 | }
41 |
42 | public static List deserializeFilterRuleList(String ruleString) {
43 | List rules = new ArrayList();
44 | String[] tokens = ruleString.split("\n");
45 | for (int i = 0; i < tokens.length; i++) {
46 | String[] values = tokens[i].split("<>");
47 | if (values.length == 2) {
48 | rules.add(new FilterRule(FilterRule.FilterRuleType.fromName(values[0]), values[1]));
49 | }
50 | }
51 | return rules;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/data/StorageDataKey.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.data;
18 |
19 | /**
20 | * Created by Wesley Lin on 11/30/14.
21 | */
22 | public class StorageDataKey {
23 | public static final String OverrideCheckBoxStatus = "AL_OverrideCheckBoxStatus";
24 |
25 | public static final String SupportedLanguageCheckStatusPrefix = "AL_SupportedLanguageCheckStatus_";
26 |
27 | // setting
28 | public static final String SettingLanguageEngine = "SettingLanguageEngine";
29 | public static final String BingClientIdStored = "BingClientIdStored";
30 | public static final String BingClientSecretStored = "BingClientSecretStored";
31 |
32 | public static final String SettingFilterRules = "SettingFilterRules";
33 |
34 | public static final String GoogleApiKeyStored = "GoogleAPIKeyStored";
35 | public static final String GoogleAlertMsgShownSetting = "GoogleAlertMsgShownSetting";
36 |
37 | public static final String BaiduClientIdStored = "BaiduClientIdStored";
38 | public static final String BaiduClientSecretStored = "BaiduClientSecretStored";
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/data/task/GetTranslationTask.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.data.task;
18 |
19 | import com.example.wujs.action.AndroidLocalization;
20 | import com.example.wujs.language_engine.TranslationEngineType;
21 | import com.example.wujs.language_engine.baidu.BaiduTranslationApi;
22 | import com.example.wujs.language_engine.google.GoogleTranslationApi;
23 | import com.example.wujs.module.AndroidString;
24 | import com.example.wujs.module.FilterRule;
25 | import com.example.wujs.module.SupportedLanguages;
26 | import com.intellij.ide.util.PropertiesComponent;
27 | import com.intellij.openapi.application.ApplicationManager;
28 | import com.intellij.openapi.fileEditor.FileEditorManager;
29 | import com.intellij.openapi.progress.ProgressIndicator;
30 | import com.intellij.openapi.progress.Task;
31 | import com.intellij.openapi.project.Project;
32 | import com.intellij.openapi.vfs.LocalFileSystem;
33 | import com.intellij.openapi.vfs.VirtualFile;
34 | import com.example.wujs.data.Log;
35 | import com.example.wujs.data.SerializeUtil;
36 | import com.example.wujs.data.StorageDataKey;
37 | import org.jetbrains.annotations.NotNull;
38 | import org.jetbrains.annotations.Nullable;
39 |
40 | import java.io.*;
41 | import java.util.ArrayList;
42 | import java.util.List;
43 |
44 | /**
45 | * Created by Wesley Lin on 12/1/14.
46 | */
47 | public class GetTranslationTask extends Task.Backgroundable {
48 |
49 | private List selectedLanguages;
50 | private final List androidStrings;
51 | private double indicatorFractionFrame;
52 | private TranslationEngineType translationEngineType;
53 | private boolean override;
54 | private VirtualFile clickedFile;
55 |
56 | private static final String BingIdInvalid = "Invalid client id or client secret, " +
57 | "please check them here";
58 | private static final String BingQuotaExceeded = "Microsoft Translator quota exceeded, " +
59 | "please check your data usage here";
60 |
61 | private static final String GoogleErrorUnknown = "Error, please check API key in the settings panel.";
62 | private static final String GoogleDailyLimitError = "Daily Limit Exceeded, please note that Google Translation API " +
63 | "is a paid service.";
64 |
65 | private String errorMsg = null;
66 |
67 | public GetTranslationTask(Project project, String title,
68 | List selectedLanguages,
69 | List androidStrings,
70 | TranslationEngineType translationEngineType,
71 | boolean override,
72 | VirtualFile clickedFile) {
73 | super(project, title);
74 | this.selectedLanguages = selectedLanguages;
75 | this.androidStrings = androidStrings;
76 | this.translationEngineType = translationEngineType;
77 | this.indicatorFractionFrame = 1.0d / (double) (this.selectedLanguages.size());
78 | this.override = override;
79 | this.clickedFile = clickedFile;
80 | }
81 |
82 | @Override
83 | public void run(ProgressIndicator indicator) {
84 | for (int i = 0; i < selectedLanguages.size(); i++) {
85 |
86 | SupportedLanguages language = selectedLanguages.get(i);
87 |
88 | if (language != null && !"".equals(language) && !language.equals(SupportedLanguages.English)) {
89 |
90 | List androidStringList = filterAndroidString(androidStrings, language, override);
91 |
92 | List> filteredAndSplittedString
93 | = splitAndroidString(androidStringList, translationEngineType);
94 |
95 | List translationResult = new ArrayList();
96 | for (int j = 0; j < filteredAndSplittedString.size(); j++) {
97 |
98 | List strings = getTranslationEngineResult(
99 | filteredAndSplittedString.get(j),
100 | language,
101 | SupportedLanguages.AUTO_BAIDU,
102 | translationEngineType
103 | );
104 |
105 | if (strings == null) {
106 | Log.i("language===" + language);
107 | continue;
108 | }
109 | translationResult.addAll(strings);
110 | indicator.setFraction(indicatorFractionFrame * (double) (i)
111 | + indicatorFractionFrame / filteredAndSplittedString.size() * (double) (j));
112 | indicator.setText("Translating to " + language.getLanguageEnglishDisplayName()
113 | + " (" + language.getLanguageDisplayName() + ")");
114 | }
115 | String fileName = getValueResourcePath(language);
116 | List fileContent = getTargetAndroidStrings(androidStrings, translationResult, fileName, override);
117 | writeAndroidStringToLocal(myProject, fileName, fileContent);
118 | }
119 | }
120 | }
121 |
122 |
123 | @Override
124 | public void onSuccess() {
125 |
126 | if (errorMsg == null || errorMsg.isEmpty())
127 | return;
128 | AndroidLocalization.showSuccessDialog(getProject(), "translation Success");
129 | }
130 |
131 | private String getValueResourcePath(SupportedLanguages language) {
132 | String resPath = clickedFile.getPath().substring(0,
133 | clickedFile.getPath().indexOf("/res/") + "/res/".length());
134 |
135 | return resPath + "values-" + language.getAndroidStringFolderNameSuffix()
136 | + "/" + clickedFile.getName();
137 | }
138 |
139 | // todo: if got error message, should break the background task
140 | private List getTranslationEngineResult(@NotNull List needToTranslatedString,
141 | @NotNull SupportedLanguages targetLanguageCode,
142 | @NotNull SupportedLanguages sourceLanguageCode,
143 | TranslationEngineType translationEngineType) {
144 |
145 | List querys = AndroidString.getAndroidStringValues(needToTranslatedString);
146 | Log.i(querys.toString());
147 |
148 | List result = null;
149 |
150 | switch (translationEngineType) {
151 | case Baidu:
152 | result = BaiduTranslationApi
153 | .getTranslationJSON(querys,targetLanguageCode,sourceLanguageCode);
154 | break;
155 | case Bing:
156 | break;
157 | case Google:
158 | result = GoogleTranslationApi
159 | .getTranslationJSON(querys, targetLanguageCode, sourceLanguageCode);
160 | if (result == null) {
161 | errorMsg = GoogleErrorUnknown;
162 | return null;
163 | } else if (result.isEmpty() && !querys.isEmpty()) {
164 | errorMsg = GoogleDailyLimitError;
165 | return null;
166 | }
167 | break;
168 | }
169 | if (result == null || result.size() <= 0){
170 | return null;
171 | }
172 | List translatedAndroidStrings = new ArrayList<>();
173 | // Logger.error(needToTranslatedString.size());
174 | // Logger.info("needToTranslatedString.size(): " + needToTranslatedString.size()+
175 | // "result.size(): " + result.size());
176 | for (int i = 0; i < needToTranslatedString.size(); i++) {
177 | translatedAndroidStrings.add(new AndroidString(
178 | needToTranslatedString.get(i).getKey(), result.get(i)));
179 | }
180 | return translatedAndroidStrings;
181 | }
182 |
183 | private List> splitAndroidString(List origin, TranslationEngineType engineType) {
184 |
185 | List> splited = new ArrayList>();
186 | int splitFragment = 50;
187 | switch (engineType) {
188 | case Baidu:
189 | splitFragment = 50;
190 | break;
191 | case Bing:
192 | splitFragment = 50;
193 | break;
194 | case Google:
195 | splitFragment = 50;
196 | break;
197 | }
198 |
199 | if (origin != null && origin.size() > 0) {
200 | if (origin.size() <= splitFragment) {
201 | splited.add(origin);
202 | } else {
203 | int count = (origin.size() % splitFragment == 0) ? (origin.size() / splitFragment) : (origin.size() / splitFragment + 1);
204 | for (int i = 1; i <= count; i++) {
205 | int end = i * splitFragment;
206 | if (end > origin.size()) {
207 | end = origin.size();
208 | }
209 |
210 | splited.add(origin.subList((i - 1) * splitFragment, end));
211 | }
212 | }
213 | }
214 |
215 | return splited;
216 | }
217 |
218 | private List filterAndroidString(List origin,
219 | SupportedLanguages language,
220 | boolean override) {
221 | List result = new ArrayList();
222 |
223 |
224 | VirtualFile targetStringFile = LocalFileSystem.getInstance().findFileByPath(
225 | getValueResourcePath(language));
226 | List targetAndroidStrings = new ArrayList();
227 | if (targetStringFile != null) {
228 | try {
229 | targetAndroidStrings = AndroidString.getAndroidStringsList(targetStringFile.contentsToByteArray());
230 | } catch (IOException e1) {
231 | e1.printStackTrace();
232 | }
233 | }
234 |
235 | String rulesString = PropertiesComponent.getInstance().getValue(StorageDataKey.SettingFilterRules);
236 | List filterRules = new ArrayList();
237 | if (rulesString == null) {
238 | filterRules.add(FilterRule.DefaultFilterRule);
239 | } else {
240 | filterRules = SerializeUtil.deserializeFilterRuleList(rulesString);
241 | }
242 | // Log.i("targetAndroidString: " + targetAndroidStrings.toString());
243 | for (AndroidString androidString : origin) {
244 | // filter rules
245 | if (FilterRule.inFilterRule(androidString.getKey(), filterRules))
246 | continue;
247 |
248 | // override
249 | /*if (!override && !targetAndroidStrings.isEmpty()) {
250 | // check if there is the androidString in this file
251 | // if there is, filter it
252 | if (isAndroidStringListContainsKey(targetAndroidStrings, androidString.getKey())) {
253 | continue;
254 | }
255 | }*/
256 |
257 | result.add(androidString);
258 | }
259 |
260 | return result;
261 | }
262 |
263 | private static List getTargetAndroidStrings(List sourceAndroidStrings,
264 | List translatedAndroidStrings,
265 | String fileName,
266 | boolean override) {
267 |
268 | if (translatedAndroidStrings == null) {
269 | translatedAndroidStrings = new ArrayList();
270 | }
271 |
272 | VirtualFile existenceFile = LocalFileSystem.getInstance().findFileByPath(fileName);
273 | List existenceAndroidStrings = null;
274 | if (existenceFile != null && !override) {
275 | try {
276 | // existenceAndroidStrings = AndroidString.getAndroidStringsList(existenceFile.contentsToByteArray());
277 | existenceAndroidStrings = AndroidString.getAndroidStrings(existenceFile.getInputStream());
278 | } catch (IOException e) {
279 | e.printStackTrace();
280 | }
281 | } else {
282 | existenceAndroidStrings = new ArrayList();
283 | }
284 |
285 | Log.i("sourceAndroidStrings: " + sourceAndroidStrings,
286 | "translatedAndroidStrings: " + translatedAndroidStrings,
287 | "existenceAndroidStrings: " + existenceAndroidStrings);
288 |
289 | List targetAndroidStrings = new ArrayList();
290 |
291 | for (int i = 0; i < sourceAndroidStrings.size(); i++) {
292 | AndroidString string = sourceAndroidStrings.get(i);
293 | AndroidString resultString = new AndroidString(string);
294 |
295 | // if override is checked, skip setting the existence value, for performance issue
296 | if (!override) {
297 | String existenceValue = getAndroidStringValueInList(existenceAndroidStrings, resultString.getKey());
298 | if (existenceValue != null) {
299 | resultString.setValue(existenceValue);
300 | }
301 | }
302 |
303 | String translatedValue = getAndroidStringValueInList(translatedAndroidStrings, resultString.getKey());
304 | if (translatedValue != null) {
305 | resultString.setValue(translatedValue);
306 | }
307 |
308 | targetAndroidStrings.add(resultString);
309 | }
310 | Log.i("targetAndroidStrings: " + targetAndroidStrings);
311 | return targetAndroidStrings;
312 | }
313 |
314 | private static void writeAndroidStringToLocal(final Project myProject, String filePath, List fileContent) {
315 | File file = new File(filePath);
316 | final VirtualFile virtualFile;
317 | boolean fileExits = true;
318 | try {
319 | file.getParentFile().mkdirs();
320 | if (!file.exists()) {
321 | fileExits = false;
322 | file.createNewFile();
323 | }
324 | //Change by GodLikeThomas FIX: Appeared Messy code under windows --start;
325 | //FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
326 | //BufferedWriter writer = new BufferedWriter(fileWriter);
327 | //writer.write(getFileContent(fileContent));
328 | //writer.close();
329 | FileOutputStream fos = new FileOutputStream(file.getAbsoluteFile());
330 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
331 | osw.write(getFileContent(fileContent));
332 | osw.close();
333 | //Change by GodLikeThomas FIX: Appeared Messy code under windows --end;
334 | } catch (IOException e) {
335 | e.printStackTrace();
336 | }
337 |
338 | if (fileExits) {
339 | virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
340 | if (virtualFile == null)
341 | return;
342 | virtualFile.refresh(true, false, new Runnable() {
343 | @Override
344 | public void run() {
345 | openFileInEditor(myProject, virtualFile);
346 | }
347 | });
348 | } else {
349 | virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
350 | openFileInEditor(myProject, virtualFile);
351 | }
352 | }
353 |
354 | private static void openFileInEditor(final Project myProject, @Nullable final VirtualFile file) {
355 | if (file == null)
356 | return;
357 |
358 | // run in UI thread:
359 | // https://theantlrguy.atlassian.net/wiki/display/~admin/Intellij+plugin+development+notes#Intellijplugindevelopmentnotes-GUIandthreads,backgroundtasks
360 | ApplicationManager.getApplication().invokeLater(new Runnable() {
361 | @Override
362 | public void run() {
363 | final FileEditorManager editorManager = FileEditorManager.getInstance(myProject);
364 | editorManager.openFile(file, true);
365 | }
366 | });
367 | }
368 |
369 | private static String getFileContent(List fileContent) {
370 | String xmlHeader = "\n";
371 | String stringResourceHeader = "\n\n";
372 | String stringResourceTail = "\n";
373 |
374 | StringBuilder sb = new StringBuilder();
375 | sb.append(xmlHeader).append(stringResourceHeader);
376 | for (AndroidString androidString : fileContent) {
377 | sb.append("\t").append(androidString.toString()).append("\n");
378 | }
379 | sb.append("\n").append(stringResourceTail);
380 | return sb.toString();
381 | }
382 |
383 | private static boolean isAndroidStringListContainsKey(List androidStrings, String key) {
384 | List keys = AndroidString.getAndroidStringKeys(androidStrings);
385 | return keys.contains(key);
386 | }
387 |
388 | public static String getAndroidStringValueInList(List androidStrings, String key) {
389 | for (AndroidString androidString : androidStrings) {
390 | if (androidString.getKey().equals(key)) {
391 | return androidString.getValue();
392 | }
393 | }
394 | return null;
395 | }
396 |
397 | }
398 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/HttpUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine;
18 |
19 | import com.intellij.openapi.util.io.StreamUtil;
20 | import org.apache.http.*;
21 | import org.apache.http.client.HttpClient;
22 | import org.apache.http.client.entity.UrlEncodedFormEntity;
23 | import org.apache.http.client.methods.HttpGet;
24 | import org.apache.http.client.methods.HttpPost;
25 | import org.apache.http.entity.StringEntity;
26 | import org.apache.http.impl.client.DefaultHttpClient;
27 | import org.apache.http.message.BasicHeader;
28 |
29 | import java.io.InputStream;
30 | import java.util.List;
31 |
32 | /**
33 | * Created by Wesley Lin on 12/2/14.
34 | */
35 | public class HttpUtils {
36 |
37 | public static String doHttpGet(String url) {
38 | try {
39 | HttpClient httpClient = new DefaultHttpClient();
40 | HttpGet httpGet = new HttpGet(url);
41 | HttpResponse resp = httpClient.execute(httpGet);
42 |
43 | return StreamUtil.readText(resp.getEntity().getContent(), "UTF-8");
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | }
47 | return null;
48 | }
49 |
50 | public static String doHttpGet(String url, Header[] headers) {
51 | try {
52 | HttpClient httpClient = new DefaultHttpClient();
53 | HttpGet httpGet = new HttpGet(url);
54 | httpGet.setHeaders(headers);
55 | HttpResponse resp = httpClient.execute(httpGet);
56 |
57 | return StreamUtil.readText(resp.getEntity().getContent(), "UTF-8");
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | }
61 | return null;
62 | }
63 |
64 | public static String doHttpPost(String url, List params) {
65 | try {
66 | HttpClient httpClient = new DefaultHttpClient();
67 | HttpPost httpPost = new HttpPost(url);
68 | httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
69 | HttpResponse resp = httpClient.execute(httpPost);
70 | return StreamUtil.readText(resp.getEntity().getContent(), "UTF-8");
71 | } catch (Exception e) {
72 | e.printStackTrace();
73 | }
74 | return null;
75 | }
76 |
77 | public static String doHttpPost(String url, String xmlBody, Header[] headers) {
78 | try {
79 | HttpClient httpClient = new DefaultHttpClient();
80 | HttpPost httpPost = new HttpPost(url);
81 | httpPost.setHeaders(headers);
82 | httpPost.setEntity(new StringEntity(xmlBody, "UTF-8"));
83 | HttpResponse resp = httpClient.execute(httpPost);
84 | return StreamUtil.readText(resp.getEntity().getContent(), "UTF-8");
85 | } catch (Exception e) {
86 | e.printStackTrace();
87 | }
88 | return null;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/TranslationEngineType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine;
18 |
19 | /**
20 | * Created by Wesley Lin on 12/2/14.
21 | */
22 | public enum TranslationEngineType {
23 | Baidu("Baidu Translator"),
24 | Bing("Microsoft Translator"),
25 | Google("Google Translation API");
26 |
27 | private String displayName;
28 |
29 | TranslationEngineType(String displayName) {
30 | this.displayName = displayName;
31 | }
32 |
33 | public String getDisplayName() {
34 | return displayName;
35 | }
36 |
37 | public static TranslationEngineType[] getLanguageEngineArray() {
38 | return new TranslationEngineType[]{
39 | Baidu,
40 | Bing,
41 | Google
42 | };
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return getDisplayName();
48 | }
49 |
50 | public static TranslationEngineType fromName(String name) {
51 | if (name == null){
52 | return Baidu;
53 | }
54 | for (TranslationEngineType type : values()) {
55 | if (type.name().equals(name)) {
56 | return type;
57 | }
58 | }
59 | return Baidu;
60 | }
61 |
62 | public String toName() {
63 | return name();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/baidu/BaiduTranslationApi.java:
--------------------------------------------------------------------------------
1 | package com.example.wujs.language_engine.baidu;
2 |
3 |
4 | import com.example.wujs.data.Key;
5 | import com.example.wujs.data.StorageDataKey;
6 | import com.example.wujs.module.SupportedLanguages;
7 | import com.example.wujs.util.Logger;
8 | import com.google.gson.JsonArray;
9 | import com.google.gson.JsonElement;
10 | import com.google.gson.JsonObject;
11 | import com.google.gson.JsonParser;
12 | import com.intellij.ide.util.PropertiesComponent;
13 | import com.example.wujs.language_engine.HttpUtils;
14 | import org.apache.http.message.BasicNameValuePair;
15 | import org.jetbrains.annotations.NotNull;
16 |
17 | import java.net.URLEncoder;
18 | import java.util.*;
19 |
20 | public class BaiduTranslationApi {
21 | private static final String TRANS_API_HOST = "http://api.fanyi.baidu.com/api/trans/vip/translate";
22 | private static final int MAX_BYTE = 6000;
23 |
24 | private String appid;
25 | private String securityKey;
26 |
27 | public BaiduTranslationApi(String appid, String securityKey) {
28 | this.appid = appid;
29 | this.securityKey = securityKey;
30 | }
31 |
32 | /**
33 | * @param querys
34 | * @param targetLanguageCode
35 | * @param sourceLanguageCode
36 | * @return
37 | */
38 | public static List getTranslationJSON(@NotNull List querys,
39 | @NotNull SupportedLanguages targetLanguageCode,
40 | @NotNull SupportedLanguages sourceLanguageCode) {
41 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
42 | if (querys.size() > 0) {
43 | List results = new ArrayList<>();
44 | for (String query : querys) {
45 | Map params = new HashMap<>();
46 | params.put("q", query);
47 | params.put("from", sourceLanguageCode.getLanguageCode());
48 | params.put("to", targetLanguageCode.getLanguageCode());
49 | String appid = new BasicNameValuePair("client_id",
50 | propertiesComponent.getValue(StorageDataKey.BaiduClientIdStored, Key.BAIDU_CLIENT_ID)).getValue();
51 | params.put("appid", appid);
52 | if (appid.isEmpty()) {
53 | Logger.error("Please input your Baidu APPID");
54 | }
55 | // 随机数
56 | String salt = String.valueOf(System.currentTimeMillis());
57 | params.put("salt", salt);
58 |
59 | String securityKey = new BasicNameValuePair("client_secret",
60 | propertiesComponent.getValue(StorageDataKey.BaiduClientSecretStored, Key.BAIDU_CLIENT_SECRET)).getValue();
61 | if (securityKey.isEmpty()) {
62 | Logger.error("Please input your Baidu SecretKey");
63 | }
64 | // 签名
65 | String src = appid + query + salt + securityKey; // 加密前的原文
66 | params.put("sign", MD5.md5(src));
67 | String getResult = HttpGet.get(TRANS_API_HOST, params);
68 | if (getResult != null) {
69 | JsonObject resultObj = new JsonParser().parse(getResult).getAsJsonObject();
70 | JsonElement errorElement = resultObj.get("error_code");
71 | if (errorElement != null) {
72 | String errorCode = errorElement.getAsString();
73 | String errorMsg = resultObj.get("error_msg").getAsString();
74 | Logger.error(errorCode + " :" + errorMsg);
75 | return null;
76 | } else {
77 | JsonArray translations = resultObj.getAsJsonArray("trans_result");
78 | if (translations != null) {
79 | String result = translations.get(0).getAsJsonObject().get("dst").getAsString();
80 | results.add(result);
81 | }
82 | }
83 | } else {
84 | return null;
85 | }
86 | }
87 | return results;
88 | }
89 | // baiduTranslate(propertiesComponent,querys, targetLanguageCode, sourceLanguageCode);
90 | return null;
91 | }
92 |
93 | private static List baiduTranslate(PropertiesComponent propertiesComponent, List querys,
94 | SupportedLanguages targetLanguageCode, SupportedLanguages sourceLanguageCode) {
95 | if (querys.isEmpty())
96 | return null;
97 | List queryBuilders = new ArrayList<>();
98 | StringBuilder queryBuilder = new StringBuilder();
99 | for (int i = 0; i < querys.size(); i++) {
100 | queryBuilder.append(querys.get(i)).append("\n");
101 | int nexLength = (i + 1) == querys.size() ? -1 : querys.get(i + 1).getBytes().length;
102 | if (queryBuilder.toString().getBytes().length + nexLength > MAX_BYTE) {
103 | queryBuilders.add(queryBuilder);
104 | queryBuilder = new StringBuilder();
105 | }
106 | if (i == querys.size() - 1) {
107 | queryBuilders.add(queryBuilder);
108 | }
109 | }
110 |
111 | if (queryBuilders.size() > 0) {
112 | List results = new ArrayList<>();
113 | for (StringBuilder builder : queryBuilders) {
114 | String query = builder.toString();
115 | Map params = new HashMap<>();
116 | params.put("q", query);
117 | params.put("from", sourceLanguageCode.getLanguageCode());
118 | params.put("to", targetLanguageCode.getLanguageCode());
119 | String appid = new BasicNameValuePair("client_id",
120 | propertiesComponent.getValue(StorageDataKey.BaiduClientIdStored, Key.BAIDU_CLIENT_ID)).getValue();
121 | params.put("appid", appid);
122 | if (appid.isEmpty()) {
123 | Logger.error("Please input your Baidu APPID");
124 | }
125 | // 随机数
126 | String salt = String.valueOf(System.currentTimeMillis());
127 | params.put("salt", salt);
128 |
129 | String securityKey = new BasicNameValuePair("client_secret",
130 | propertiesComponent.getValue(StorageDataKey.BaiduClientSecretStored, Key.BAIDU_CLIENT_SECRET)).getValue();
131 | if (securityKey.isEmpty()) {
132 | Logger.error("Please input your Baidu SecretKey");
133 | }
134 | // 签名
135 | String src = appid + query + salt + securityKey; // 加密前的原文
136 | params.put("sign", MD5.md5(src));
137 | String getResult = HttpGet.get(TRANS_API_HOST, params);
138 | if (getResult != null) {
139 | Logger.error(getResult);
140 | JsonObject resultObj = new JsonParser().parse(getResult).getAsJsonObject();
141 | JsonElement errorElement = resultObj.get("error_code");
142 | if (errorElement != null) {
143 | String errorCode = errorElement.getAsString();
144 | String errorMsg = resultObj.get("error_msg").getAsString();
145 | Logger.error(errorCode + " :" + errorMsg);
146 | return null;
147 | } else {
148 | JsonArray translations = resultObj.getAsJsonArray("trans_result");
149 | if (translations != null) {
150 | List result = new ArrayList<>();
151 | for (int i = 0; i < translations.size(); i++) {
152 | result.add(translations.get(i).getAsJsonObject().get("dst").getAsString());
153 | }
154 | results.addAll(result);
155 |
156 | }
157 | }
158 | } else {
159 | return null;
160 | }
161 | }
162 | return results;
163 | }
164 | return null;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/baidu/HttpGet.java:
--------------------------------------------------------------------------------
1 | package com.example.wujs.language_engine.baidu;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.Closeable;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 | import java.io.UnsupportedEncodingException;
9 | import java.net.HttpURLConnection;
10 | import java.net.MalformedURLException;
11 | import java.net.URL;
12 | import java.net.URLEncoder;
13 | import java.security.KeyManagementException;
14 | import java.security.NoSuchAlgorithmException;
15 | import java.security.cert.CertificateException;
16 | import java.security.cert.X509Certificate;
17 | import java.util.Map;
18 |
19 | import javax.net.ssl.HttpsURLConnection;
20 | import javax.net.ssl.SSLContext;
21 | import javax.net.ssl.TrustManager;
22 | import javax.net.ssl.X509TrustManager;
23 |
24 | class HttpGet {
25 | protected static final int SOCKET_TIMEOUT = 10000; // 10S
26 | protected static final String GET = "GET";
27 |
28 | public static String get(String host, Map params) {
29 | try {
30 | // 设置SSLContext
31 | SSLContext sslcontext = SSLContext.getInstance("TLS");
32 | sslcontext.init(null, new TrustManager[] { myX509TrustManager }, null);
33 |
34 | String sendUrl = getUrlWithQueryString(host, params);
35 |
36 | // System.out.println("URL:" + sendUrl);
37 |
38 | URL uri = new URL(sendUrl); // 创建URL对象
39 | HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
40 | if (conn instanceof HttpsURLConnection) {
41 | ((HttpsURLConnection) conn).setSSLSocketFactory(sslcontext.getSocketFactory());
42 | }
43 |
44 | conn.setConnectTimeout(SOCKET_TIMEOUT); // 设置相应超时
45 | conn.setRequestMethod(GET);
46 | int statusCode = conn.getResponseCode();
47 | if (statusCode != HttpURLConnection.HTTP_OK) {
48 | System.out.println("Http错误码:" + statusCode);
49 | }
50 |
51 | // 读取服务器的数据
52 | InputStream is = conn.getInputStream();
53 | BufferedReader br = new BufferedReader(new InputStreamReader(is));
54 | StringBuilder builder = new StringBuilder();
55 | String line = null;
56 | while ((line = br.readLine()) != null) {
57 | builder.append(line);
58 | }
59 |
60 | String text = builder.toString();
61 |
62 | close(br); // 关闭数据流
63 | close(is); // 关闭数据流
64 | conn.disconnect(); // 断开连接
65 |
66 | return text;
67 | } catch (MalformedURLException e) {
68 | e.printStackTrace();
69 | } catch (IOException e) {
70 | e.printStackTrace();
71 | } catch (KeyManagementException e) {
72 | e.printStackTrace();
73 | } catch (NoSuchAlgorithmException e) {
74 | e.printStackTrace();
75 | }
76 |
77 | return null;
78 | }
79 |
80 | public static String getUrlWithQueryString(String url, Map params) {
81 | if (params == null) {
82 | return url;
83 | }
84 |
85 | StringBuilder builder = new StringBuilder(url);
86 | if (url.contains("?")) {
87 | builder.append("&");
88 | } else {
89 | builder.append("?");
90 | }
91 |
92 | int i = 0;
93 | for (String key : params.keySet()) {
94 | String value = params.get(key);
95 | if (value == null) { // 过滤空的key
96 | continue;
97 | }
98 |
99 | if (i != 0) {
100 | builder.append('&');
101 | }
102 |
103 | builder.append(key);
104 | builder.append('=');
105 | builder.append(encode(value));
106 |
107 | i++;
108 | }
109 |
110 | return builder.toString();
111 | }
112 |
113 | protected static void close(Closeable closeable) {
114 | if (closeable != null) {
115 | try {
116 | closeable.close();
117 | } catch (IOException e) {
118 | e.printStackTrace();
119 | }
120 | }
121 | }
122 |
123 | /**
124 | * 对输入的字符串进行URL编码, 即转换为%20这种形式
125 | *
126 | * @param input 原文
127 | * @return URL编码. 如果编码失败, 则返回原文
128 | */
129 | public static String encode(String input) {
130 | if (input == null) {
131 | return "";
132 | }
133 |
134 | try {
135 | return URLEncoder.encode(input, "utf-8");
136 | } catch (UnsupportedEncodingException e) {
137 | e.printStackTrace();
138 | }
139 |
140 | return input;
141 | }
142 |
143 | private static TrustManager myX509TrustManager = new X509TrustManager() {
144 |
145 | @Override
146 | public X509Certificate[] getAcceptedIssuers() {
147 | return null;
148 | }
149 |
150 | @Override
151 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
152 | }
153 |
154 | @Override
155 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
156 | }
157 | };
158 |
159 | }
160 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/baidu/MD5.java:
--------------------------------------------------------------------------------
1 | package com.example.wujs.language_engine.baidu;
2 |
3 | import java.io.*;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 |
7 | /**
8 | * MD5编码相关的类
9 | *
10 | * @author wangjingtao
11 | *
12 | */
13 | public class MD5 {
14 | // 首先初始化一个字符数组,用来存放每个16进制字符
15 | private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
16 | 'e', 'f' };
17 |
18 | /**
19 | * 获得一个字符串的MD5值
20 | *
21 | * @param input 输入的字符串
22 | * @return 输入字符串的MD5值
23 | *
24 | */
25 | public static String md5(String input) {
26 | if (input == null)
27 | return null;
28 |
29 | try {
30 | // 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)
31 | MessageDigest messageDigest = MessageDigest.getInstance("MD5");
32 | // 输入的字符串转换成字节数组
33 | byte[] inputByteArray = new byte[0];
34 | try {
35 | inputByteArray = input.getBytes("utf-8");
36 | } catch (UnsupportedEncodingException e) {
37 | e.printStackTrace();
38 | }
39 | // inputByteArray是输入字符串转换得到的字节数组
40 | messageDigest.update(inputByteArray);
41 | // 转换并返回结果,也是字节数组,包含16个元素
42 | byte[] resultByteArray = messageDigest.digest();
43 | // 字符数组转换成字符串返回
44 | return byteArrayToHex(resultByteArray);
45 | } catch (NoSuchAlgorithmException e) {
46 | return null;
47 | }
48 | }
49 |
50 | /**
51 | * 获取文件的MD5值
52 | *
53 | * @param file
54 | * @return
55 | */
56 | public static String md5(File file) {
57 | try {
58 | if (!file.isFile()) {
59 | System.err.println("文件" + file.getAbsolutePath() + "不存在或者不是文件");
60 | return null;
61 | }
62 |
63 | FileInputStream in = new FileInputStream(file);
64 |
65 | String result = md5(in);
66 |
67 | in.close();
68 |
69 | return result;
70 |
71 | } catch (FileNotFoundException e) {
72 | e.printStackTrace();
73 | } catch (IOException e) {
74 | e.printStackTrace();
75 | }
76 |
77 | return null;
78 | }
79 |
80 | public static String md5(InputStream in) {
81 |
82 | try {
83 | MessageDigest messagedigest = MessageDigest.getInstance("MD5");
84 |
85 | byte[] buffer = new byte[1024];
86 | int read = 0;
87 | while ((read = in.read(buffer)) != -1) {
88 | messagedigest.update(buffer, 0, read);
89 | }
90 |
91 | in.close();
92 |
93 | String result = byteArrayToHex(messagedigest.digest());
94 |
95 | return result;
96 | } catch (NoSuchAlgorithmException e) {
97 | e.printStackTrace();
98 | } catch (FileNotFoundException e) {
99 | e.printStackTrace();
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | }
103 |
104 | return null;
105 | }
106 |
107 | private static String byteArrayToHex(byte[] byteArray) {
108 | // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
109 | char[] resultCharArray = new char[byteArray.length * 2];
110 | // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
111 | int index = 0;
112 | for (byte b : byteArray) {
113 | resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
114 | resultCharArray[index++] = hexDigits[b & 0xf];
115 | }
116 |
117 | // 字符数组组合成字符串返回
118 | return new String(resultCharArray);
119 |
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/bing/BingResultParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine.bing;
18 |
19 |
20 | import javax.xml.stream.XMLEventReader;
21 | import javax.xml.stream.XMLInputFactory;
22 | import javax.xml.stream.XMLStreamException;
23 | import javax.xml.stream.events.Attribute;
24 | import javax.xml.stream.events.EndElement;
25 | import javax.xml.stream.events.StartElement;
26 | import javax.xml.stream.events.XMLEvent;
27 | import java.io.ByteArrayInputStream;
28 | import java.io.InputStream;
29 | import java.nio.charset.Charset;
30 | import java.util.ArrayList;
31 | import java.util.Iterator;
32 | import java.util.List;
33 |
34 | /**
35 | * Created by Wesley Lin on 12/5/14.
36 | */
37 | public class BingResultParser {
38 | static final String TranslateArrayResponse = "TranslateArrayResponse";
39 | static final String From = "From";
40 | static final String TranslatedText = "TranslatedText";
41 |
42 | public static List parseTranslateArrayResponse(String xml) {
43 |
44 | InputStream stream = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
45 |
46 | List result = new ArrayList();
47 |
48 | try {
49 | XMLInputFactory inputFactory = XMLInputFactory.newInstance();
50 | XMLEventReader eventReader = inputFactory.createXMLEventReader(stream);
51 |
52 | TranslateArrayResponse translateArrayResponse = null;
53 |
54 | while (eventReader.hasNext()) {
55 | XMLEvent event = eventReader.nextEvent();
56 |
57 | if (event.isStartElement()) {
58 | StartElement startElement = event.asStartElement();
59 | if (startElement.getName().getLocalPart().equals(TranslateArrayResponse)) {
60 | translateArrayResponse = new TranslateArrayResponse();
61 | }
62 | if (event.isStartElement()) {
63 | if (event.asStartElement().getName().getLocalPart().equals(From)) {
64 | event = eventReader.nextEvent();
65 | translateArrayResponse.setFrom(event.asCharacters().getData());
66 | continue;
67 | }
68 | }
69 | if (event.asStartElement().getName().getLocalPart().equals(TranslatedText)) {
70 | event = eventReader.nextEvent();
71 | translateArrayResponse.setTranslatedText(event.asCharacters().getData());
72 | continue;
73 | }
74 | }
75 |
76 | if (event.isEndElement()) {
77 | EndElement endElement = event.asEndElement();
78 | if (endElement.getName().getLocalPart().equals(TranslateArrayResponse)) {
79 | result.add(translateArrayResponse);
80 | }
81 | }
82 | }
83 | } catch (XMLStreamException e) {
84 | e.printStackTrace();
85 | }
86 |
87 | return result;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/bing/BingTranslationApi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine.bing;
18 |
19 | import com.example.wujs.data.Key;
20 | import com.example.wujs.data.Log;
21 | import com.example.wujs.data.StorageDataKey;
22 | import com.example.wujs.module.SupportedLanguages;
23 | import com.google.gson.JsonArray;
24 | import com.google.gson.JsonObject;
25 | import com.google.gson.JsonParser;
26 | import com.google.gson.JsonSyntaxException;
27 | import com.intellij.ide.util.PropertiesComponent;
28 | import com.example.wujs.language_engine.HttpUtils;
29 | import org.apache.commons.lang.StringEscapeUtils;
30 | import org.apache.http.Header;
31 | import org.apache.http.NameValuePair;
32 | import org.apache.http.message.BasicHeader;
33 | import org.apache.http.message.BasicNameValuePair;
34 |
35 | import java.io.UnsupportedEncodingException;
36 | import java.net.URLEncoder;
37 | import java.util.ArrayList;
38 | import java.util.List;
39 |
40 | /**
41 | * Created by Wesley Lin on 12/3/14.
42 | */
43 | public class BingTranslationApi {
44 | private static final String ENCODING = "UTF-8";
45 |
46 | private static final String AUTH_URL = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/";
47 |
48 | private static final String TRANSLATE_URL = "http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray?";
49 |
50 | private static List getAccessTokenNameValuePair() {
51 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
52 | List params = new ArrayList(4);
53 | params.add(new BasicNameValuePair("client_id",
54 | propertiesComponent.getValue(StorageDataKey.BingClientIdStored, Key.BING_CLIENT_ID)));
55 | params.add(new BasicNameValuePair("client_secret",
56 | propertiesComponent.getValue(StorageDataKey.BingClientSecretStored, Key.BING_CLIENT_SECRET)));
57 | params.add(new BasicNameValuePair("scope", Key.BING_CLIENT_SCOPE));
58 | params.add(new BasicNameValuePair("grant_type", Key.BING_CLIENT_GRANT_TYPE));
59 | return params;
60 | }
61 |
62 | public static String getAccessToken() {
63 | String postResult = HttpUtils.doHttpPost(AUTH_URL, getAccessTokenNameValuePair());
64 | JsonObject jsonObject = new JsonParser().parse(postResult).getAsJsonObject();
65 | if (jsonObject.get("error") == null) {
66 | return jsonObject.get("access_token").getAsString();
67 | }
68 | return null;
69 | }
70 |
71 | protected static final String PARAM_APP_ID = "appId=",
72 | PARAM_TO_LANG = "&to=",
73 | PARAM_FROM_LANG = "&from=",
74 | PARAM_TEXT_ARRAY = "&texts=";
75 |
76 | /**
77 | * using AJAX api now: http://msdn.microsoft.com/en-us/library/ff512402.aspx
78 | *
79 | * @param accessToken
80 | * @param querys
81 | * @param from
82 | * @param to
83 | * @return list of String, which is the result
84 | */
85 | public static List getTranslatedStringArrays2(String accessToken, List querys, SupportedLanguages from, SupportedLanguages to) {
86 | // Log.i(querys.toString());
87 | String url = generateUrl(accessToken, querys, from, to);
88 | Header[] headers = new Header[]{
89 | new BasicHeader("Authorization", "Bearer " + accessToken),
90 | new BasicHeader("Content-Type", "text/plain; charset=" + ENCODING),
91 | new BasicHeader("Accept-Charset", ENCODING)
92 | };
93 |
94 | String getResult = HttpUtils.doHttpGet(url, headers);
95 | // Log.i(getResult);
96 | JsonArray jsonArray = null;
97 | try {
98 | jsonArray = new JsonParser().parse(getResult).getAsJsonArray();
99 | } catch (JsonSyntaxException e) {
100 | e.printStackTrace();
101 | }
102 | if (jsonArray == null)
103 | return null;
104 |
105 | // Log.i("jsonArray.size: " + jsonArray.size());
106 | List result = new ArrayList();
107 | for (int i = 0; i < jsonArray.size(); i++) {
108 | String translatedText = jsonArray.get(i).getAsJsonObject().get("TranslatedText").getAsString();
109 | if (translatedText == null) {
110 | result.add("");
111 | } else {
112 | result.add(StringEscapeUtils.unescapeJava(translatedText));
113 | }
114 | }
115 |
116 | if (querys.size() > result.size()) {
117 | for (int i = 0; i < querys.size(); i++) {
118 | if (querys.get(i).isEmpty()) {
119 | result.add(i, "");
120 | }
121 | if (querys.size() == result.size())
122 | break;
123 | }
124 | }
125 | Log.i(result.toString());
126 |
127 | return result;
128 | }
129 |
130 | private static String generateUrl(String accessToken, List querys, SupportedLanguages from, SupportedLanguages to) {
131 | String[] texts = new String[]{};
132 | texts = querys.toArray(texts);
133 | for (int i = 0; i < texts.length; i++) {
134 | texts[i] = StringEscapeUtils.escapeJava(texts[i]);
135 | }
136 |
137 | try {
138 | final String params =
139 | (accessToken != null ? PARAM_APP_ID + URLEncoder.encode("Bearer " + accessToken, ENCODING) : "")
140 | + PARAM_FROM_LANG + URLEncoder.encode(from.getLanguageCode(), ENCODING)
141 | + PARAM_TO_LANG + URLEncoder.encode(to.getLanguageCode(), ENCODING)
142 | + PARAM_TEXT_ARRAY + URLEncoder.encode(buildStringArrayParam(texts), ENCODING);
143 |
144 | return TRANSLATE_URL + params;
145 | } catch (UnsupportedEncodingException e) {
146 | e.printStackTrace();
147 | }
148 | return null;
149 | }
150 |
151 | private static String buildStringArrayParam(Object[] values) {
152 | StringBuilder targetString = new StringBuilder("[\"");
153 | String value;
154 | for (Object obj : values) {
155 | if (obj != null) {
156 | value = obj.toString();
157 | if (value.length() != 0) {
158 | if (targetString.length() > 2)
159 | targetString.append(",\"");
160 | targetString.append(value);
161 | targetString.append("\"");
162 | }
163 | }
164 | }
165 | targetString.append("]");
166 | return targetString.toString();
167 | }
168 |
169 | /**
170 | * @deprecated using @getTranslatedStringArrays2 now
171 | */
172 | public static List getTranslatedStringArrays(String accessToken, List querys, SupportedLanguages from, SupportedLanguages to) {
173 | String xmlBodyTop = "\n" +
174 | " \n" +
175 | " %s\n" +
176 | " \n" +
177 | " \n" +
178 | " text/plain\n" +
179 | " \n" +
180 | " \n" +
181 | " \n" +
182 | " \n" +
183 | " \n" +
184 | " \n";
185 |
186 | String xmlBodyMid = "%s\n";
187 | String xmlBodyBot = " \n" +
188 | " %s\n" +
189 | "";
190 |
191 | String xmlBodyStrings = "";
192 | for (String query : querys) {
193 | xmlBodyStrings += String.format(xmlBodyMid, query);
194 | }
195 |
196 | String xmlBody = String.format(xmlBodyTop, from.getLanguageCode())
197 | + xmlBodyStrings
198 | + String.format(xmlBodyBot, to.getLanguageCode());
199 |
200 | Header[] headers = new Header[]{
201 | new BasicHeader("Authorization", "Bearer " + accessToken),
202 | new BasicHeader("Content-Type", "text/xml")
203 | };
204 |
205 | Log.i("Bearer " + accessToken);
206 | Log.i("xml body: " + xmlBody);
207 |
208 | String postResult = HttpUtils.doHttpPost(TRANSLATE_URL, xmlBody, headers);
209 | Log.i("post result: " + postResult);
210 |
211 | List translateArrayResponses = BingResultParser.parseTranslateArrayResponse(postResult);
212 |
213 | List result = new ArrayList();
214 | for (TranslateArrayResponse translateArrayResponse : translateArrayResponses) {
215 | result.add(translateArrayResponse.getTranslatedText());
216 | }
217 | return result;
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/bing/TranslateArrayResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine.bing;
18 |
19 | /**
20 | * Created by Wesley Lin on 12/5/14.
21 | *
22 | * @deprecated
23 | */
24 | public class TranslateArrayResponse {
25 | private String from = "";
26 | private String translatedText = "";
27 |
28 | public String getFrom() {
29 | return from;
30 | }
31 |
32 | public void setFrom(String from) {
33 | this.from = from;
34 | }
35 |
36 |
37 | public String getTranslatedText() {
38 | return translatedText;
39 | }
40 |
41 | public void setTranslatedText(String translatedText) {
42 | this.translatedText = translatedText;
43 | }
44 |
45 | public String toString() {
46 | return "[from: " + from + ", translatedText: " + translatedText + "]";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/google/GoogleTranslationApi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.language_engine.google;
18 |
19 | import com.example.wujs.data.Log;
20 | import com.example.wujs.data.StorageDataKey;
21 | import com.example.wujs.module.SupportedLanguages;
22 | import com.google.gson.JsonArray;
23 | import com.google.gson.JsonObject;
24 | import com.google.gson.JsonParser;
25 | import com.intellij.ide.util.PropertiesComponent;
26 | import com.example.wujs.language_engine.HttpUtils;
27 | import org.apache.http.HttpEntity;
28 | import org.apache.http.HttpResponse;
29 | import org.apache.http.client.HttpClient;
30 | import org.apache.http.client.methods.HttpGet;
31 | import org.apache.http.impl.client.DefaultHttpClient;
32 | import org.apache.http.util.EntityUtils;
33 | import org.jetbrains.annotations.NotNull;
34 |
35 | import java.io.IOException;
36 | import java.net.URLEncoder;
37 | import java.util.ArrayList;
38 | import java.util.IllegalFormatException;
39 | import java.util.List;
40 |
41 |
42 | /**
43 | * Created by Wesley Lin on 12/1/14.
44 | */
45 | public class GoogleTranslationApi {
46 | private static final String BASE_TRANSLATION_URL = "https://www.googleapis.com/language/translate/v2?%s&target=%s&source=%s&key=%s";
47 | // "https://translate.google.com/?hl=zh#auto/zh-CN/%E5%9B%9E%E5%AE%B6";
48 | private static String BASE_GOOGLE_URL = "https://translate.google.com/?hl=zh#auto/%s/%s";
49 |
50 | /**
51 | * @param querys
52 | * @param targetLanguageCode
53 | * @param sourceLanguageCode
54 | * @return
55 | */
56 | public static List getTranslationJSON(@NotNull List querys,
57 | @NotNull SupportedLanguages targetLanguageCode,
58 | @NotNull SupportedLanguages sourceLanguageCode) {
59 | if (querys.isEmpty())
60 | return null;
61 |
62 | for (int i=0;i urls = new ArrayList<>();
67 | for (String q:querys){
68 | String url = String.format(BASE_GOOGLE_URL,targetLanguageCode,q);
69 | urls.add(url);
70 | }
71 |
72 | if (urls.size() >0){
73 |
74 | }
75 | String query = "";
76 | for (int i = 0; i < querys.size(); i++) {
77 | query += ("q=" + URLEncoder.encode(querys.get(i)));
78 | if (i != querys.size() - 1) {
79 | query += "&";
80 | }
81 | }
82 |
83 | String url = null;
84 | try {
85 | url = String.format(BASE_TRANSLATION_URL, query,
86 | targetLanguageCode.getLanguageCode(),
87 | sourceLanguageCode.getLanguageCode(),
88 | PropertiesComponent.getInstance().getValue(StorageDataKey.GoogleApiKeyStored), "");
89 | } catch (IllegalFormatException e) {
90 | Log.i("error====" + e.getMessage());
91 | }
92 |
93 | Log.i("url====" + url);
94 |
95 | if (url == null)
96 | return null;
97 |
98 | String getResult = HttpUtils.doHttpGet(url);
99 | Log.i("do get result: " + getResult + " url====" + url);
100 |
101 | JsonObject jsonObject = new JsonParser().parse(getResult).getAsJsonObject();
102 | if (jsonObject.get("error") != null) {
103 | JsonObject error = jsonObject.get("error").getAsJsonObject().get("errors").getAsJsonArray().get(0).getAsJsonObject();
104 | if (error == null)
105 | return null;
106 |
107 | if (error.get("reason").getAsString().equals("dailyLimitExceeded"))
108 | return new ArrayList();
109 | return null;
110 | } else {
111 | JsonObject data = jsonObject.get("data").getAsJsonObject();
112 | JsonArray translations = data.get("translations").getAsJsonArray();
113 | if (translations != null) {
114 | List result = new ArrayList();
115 | for (int i = 0; i < translations.size(); i++) {
116 | result.add(translations.get(i).getAsJsonObject().get("translatedText").getAsString());
117 | }
118 | return result;
119 | }
120 | }
121 | return null;
122 | }
123 |
124 |
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/language_engine/google/GoogleTranslationer.java:
--------------------------------------------------------------------------------
1 | package com.example.wujs.language_engine.google;
2 |
3 | import org.apache.http.HttpEntity;
4 | import org.apache.http.HttpResponse;
5 | import org.apache.http.client.HttpClient;
6 | import org.apache.http.client.methods.HttpGet;
7 | import org.apache.http.impl.client.DefaultHttpClient;
8 | import org.apache.http.util.EntityUtils;
9 |
10 | import javax.lang.model.util.Elements;
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.concurrent.CountDownLatch;
15 | import java.util.concurrent.ExecutorService;
16 | import java.util.concurrent.Executors;
17 |
18 | public class GoogleTranslationer {
19 | private ExecutorService fixedThreadPool;
20 | private CountDownLatch countDownLatch;
21 | private List result;
22 | private static int COUNT = 0;
23 |
24 | public GoogleTranslationer(List urls) {
25 | this.fixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
26 | this.countDownLatch = new CountDownLatch(urls.size());
27 | COUNT = urls.size();
28 | this.result = new ArrayList<>();
29 | }
30 |
31 | public List googleTranslate(List urls) {
32 | if (urls != null && urls.size() > 0) {
33 | for (String url : urls) {
34 | fixedThreadPool.execute(new HttpGetRunnable(url));
35 | }
36 | try {
37 | countDownLatch.await();
38 | } catch (InterruptedException e) {
39 | e.printStackTrace();
40 | }
41 | return result;
42 | }
43 | return result;
44 | }
45 |
46 |
47 | private class HttpGetRunnable implements Runnable {
48 |
49 | String url;
50 |
51 | public HttpGetRunnable(String url) {
52 | this.url = url;
53 | }
54 |
55 | @Override
56 | public void run() {
57 | String resp = httpGet(url);
58 | if (resp != null){
59 | }
60 | }
61 | }
62 |
63 | private static String httpGet(String url) {
64 | HttpClient httpClient = new DefaultHttpClient();
65 |
66 | HttpGet httpGet = new HttpGet(url);
67 | HttpResponse httpResponse;
68 | try {
69 | httpResponse = httpClient.execute(httpGet);
70 | if (httpResponse.getStatusLine().getStatusCode() == 200) {
71 | HttpEntity entity = httpResponse.getEntity();
72 | return EntityUtils.toString(entity, "utf-8");
73 | }
74 | } catch (IOException e) {
75 | e.printStackTrace();
76 | return null;
77 | }
78 | return null;
79 |
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/module/AndroidString.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.module;
18 |
19 | import com.example.wujs.util.Logger;
20 | import org.w3c.dom.Document;
21 | import org.w3c.dom.Node;
22 | import org.w3c.dom.NodeList;
23 | import org.xml.sax.SAXException;
24 |
25 | import javax.xml.stream.XMLEventReader;
26 | import javax.xml.stream.XMLInputFactory;
27 | import javax.xml.stream.XMLStreamException;
28 | import javax.xml.stream.events.Attribute;
29 | import javax.xml.stream.events.EndElement;
30 | import javax.xml.stream.events.StartElement;
31 | import javax.xml.stream.events.XMLEvent;
32 | import javax.xml.parsers.DocumentBuilder;
33 | import javax.xml.parsers.DocumentBuilderFactory;
34 | import javax.xml.parsers.ParserConfigurationException;
35 | import javax.xml.xpath.XPath;
36 | import javax.xml.parsers.DocumentBuilder;
37 | import javax.xml.parsers.DocumentBuilderFactory;
38 | import javax.xml.parsers.ParserConfigurationException;
39 | import javax.xml.xpath.XPath;
40 | import javax.xml.xpath.XPathConstants;
41 | import javax.xml.xpath.XPathExpression;
42 | import javax.xml.xpath.XPathExpressionException;
43 | import javax.xml.xpath.XPathFactory;
44 | import javax.xml.xpath.XPathFactory;
45 | import java.io.IOException;
46 | import java.io.InputStream;
47 | import java.io.UnsupportedEncodingException;
48 | import java.net.URLEncoder;
49 | import java.util.ArrayList;
50 | import java.util.Iterator;
51 | import java.util.List;
52 |
53 | /**
54 | * Created by Wesley Lin on 11/29/14.
55 | */
56 | public class AndroidString {
57 | private String key;
58 | private String value;
59 | private Document mDoc;
60 | private XPath mXPath;
61 |
62 | public AndroidString(String key, String value) {
63 | this.key = key;
64 | this.value = value;
65 | }
66 |
67 | public AndroidString(AndroidString androidString) {
68 | this.key = androidString.getKey();
69 | this.value = androidString.getValue();
70 | }
71 |
72 | public AndroidString() {
73 |
74 | }
75 |
76 | public String getKey() {
77 | return key;
78 | }
79 |
80 | public String getValue() {
81 | return value;
82 | }
83 |
84 | public void setValue(String value) {
85 | this.value = value;
86 | }
87 |
88 | public void setKey(String key) {
89 | this.key = key;
90 | }
91 |
92 | @Override
93 | public String toString() {
94 | return "" +
97 | value +
98 | "";
99 | }
100 |
101 | private static final String KEY_STRING = "";
102 | private static final String SPLIT_KEY = "";
105 | private static final String VALUE_END = "";
106 |
107 | private static final String STRING_PATH = "/resources/string";
108 | private static final String NAME_PATH = "./@name";
109 |
110 | /**
111 | * @deprecated
112 | */
113 | public static List getAndroidStringsList(InputStream xml) {
114 | List result = new ArrayList();
115 |
116 | try {
117 | XMLInputFactory inputFactory = XMLInputFactory.newInstance();
118 | XMLEventReader eventReader = inputFactory.createXMLEventReader(xml);
119 |
120 | AndroidString androidString = null;
121 |
122 | while (eventReader.hasNext()) {
123 | XMLEvent event = eventReader.nextEvent();
124 |
125 | if (event.isStartElement()) {
126 | StartElement startElement = event.asStartElement();
127 | if (startElement.getName().getLocalPart().equals("string")) {
128 | androidString = new AndroidString();
129 |
130 | Iterator attributes = startElement.getAttributes();
131 |
132 | while (attributes.hasNext()) {
133 | Attribute attribute = attributes.next();
134 | if (attribute.getName().toString().equals("name")) {
135 | androidString.setKey(attribute.getValue());
136 | }
137 | }
138 |
139 | event = eventReader.nextEvent();
140 | String value = event.asCharacters().getData().trim();
141 |
142 | // todo: if the value starts with xml tags(), the value will be empty
143 | androidString.setValue(value);
144 | continue;
145 | }
146 | }
147 |
148 | if (event.isEndElement()) {
149 | EndElement endElement = event.asEndElement();
150 | if (endElement.getName().getLocalPart().equals("string")) {
151 | result.add(androidString);
152 | }
153 | }
154 | }
155 | } catch (XMLStreamException e) {
156 | e.printStackTrace();
157 | }
158 | return result;
159 | }
160 |
161 | public static List getAndroidStrings(InputStream xml) {
162 | if (xml != null) {
163 | List androidStrings = new ArrayList<>();
164 | DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
165 | domFactory.setNamespaceAware(true); // never forget this!
166 | try {
167 | DocumentBuilder builder = domFactory.newDocumentBuilder();
168 | XPathFactory factory = XPathFactory.newInstance();
169 | XPath mXPath = factory.newXPath();
170 | try {
171 | Document doc = builder.parse(xml);
172 | XPathExpression strExpr = mXPath.compile(STRING_PATH);
173 | if (strExpr != null) {
174 | Object result = strExpr.evaluate(doc, XPathConstants.NODESET);
175 | if (result != null) {
176 | NodeList strList = (NodeList) result;
177 | XPathExpression nameExpr = mXPath.compile(NAME_PATH);
178 | if (strList.getLength() > 0) {
179 | for (int i = 0; i < strList.getLength(); i++) {
180 | Node node = strList.item(i);
181 | String name = (String) nameExpr.evaluate(node, XPathConstants.STRING);
182 | String value = node.getTextContent().trim();
183 | if (name == null || name.length() <= 0 || value.length() <= 0){
184 | Logger.warn("Warning:name or value is empty in strings.xml");
185 | }else {
186 | androidStrings.add(new AndroidString(name,value));
187 | }
188 | }
189 | return androidStrings;
190 | }
191 | }
192 | }
193 | } catch (SAXException | IOException | XPathExpressionException e) {
194 | e.printStackTrace();
195 | }
196 | } catch (ParserConfigurationException e) {
197 | e.printStackTrace();
198 | }
199 | }
200 | return null;
201 | }
202 |
203 | /**
204 | * @param xmlContentByte
205 | * @return
206 | * @deprecated
207 | */
208 | public static List getAndroidStringsList(byte[] xmlContentByte) {
209 | try {
210 | String fileContent = new String(xmlContentByte, "UTF-8");
211 |
212 | if (!fileContent.contains(KEY_STRING))
213 | return null;
214 |
215 | String[] tokens = fileContent.split(SPLIT_KEY);
216 |
217 | List result = new ArrayList();
218 |
219 | for (int i = 0; i < tokens.length; i++) {
220 |
221 | if (tokens[i].contains(KEY_STRING)) {
222 |
223 | int keyStartIndex = tokens[i].indexOf(KEY_START) + KEY_START.length();
224 | int keyEndIndex = tokens[i].indexOf(KEY_END);
225 | int valueEndIndex = tokens[i].indexOf(VALUE_END);
226 |
227 | if (keyStartIndex >= tokens[i].length()
228 | || keyEndIndex >= tokens[i].length()
229 | || (keyEndIndex + KEY_END.length()) >= tokens[i].length()
230 | || valueEndIndex >= tokens[i].length()) {
231 | continue;
232 | }
233 |
234 | String key = tokens[i].substring(keyStartIndex, keyEndIndex).trim();
235 | String value = tokens[i].substring(keyEndIndex + KEY_END.length(), valueEndIndex).trim();
236 |
237 | result.add(new AndroidString(key, value));
238 | }
239 | }
240 | return result;
241 | } catch (UnsupportedEncodingException e) {
242 | e.printStackTrace();
243 | }
244 | return null;
245 | }
246 |
247 | public static List getAndroidStringKeys(List list) {
248 | List result = new ArrayList();
249 |
250 | for (int i = 0; i < list.size(); i++) {
251 | result.add(list.get(i).getKey());
252 | }
253 | return result;
254 | }
255 |
256 | public static List getAndroidStringValues(List list) {
257 | List result = new ArrayList();
258 |
259 | for (int i = 0; i < list.size(); i++) {
260 | result.add(list.get(i).getValue());
261 | }
262 | return result;
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/module/FilterRule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.module;
18 |
19 | import com.example.wujs.data.SerializeUtil;
20 | import com.example.wujs.data.StorageDataKey;
21 | import com.intellij.ide.util.PropertiesComponent;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * Created by Wesley Lin on 12/14/14.
28 | */
29 | public class FilterRule {
30 |
31 | private FilterRuleType filterRuleType;
32 | private String filterString;
33 |
34 | public FilterRule(FilterRuleType filterRuleType, String filterString) {
35 | this.filterRuleType = filterRuleType;
36 | this.filterString = filterString;
37 | }
38 |
39 | public FilterRuleType getFilterRuleType() {
40 | return filterRuleType;
41 | }
42 |
43 | public String getFilterString() {
44 | return filterString;
45 | }
46 |
47 | public void setFilterRuleType(FilterRuleType filterRuleType) {
48 | this.filterRuleType = filterRuleType;
49 | }
50 |
51 | public void setFilterString(String filterString) {
52 | this.filterString = filterString;
53 | }
54 |
55 | public static FilterRule DefaultFilterRule = new FilterRule(FilterRuleType.START_WITH, "NAL_");
56 |
57 | public String toString() {
58 | return getFilterRuleType().toString() + " <" + getFilterString() + ">";
59 | }
60 |
61 | public static List getFilterRulesFromLocal() {
62 | List result = new ArrayList();
63 |
64 | String rules = PropertiesComponent.getInstance().getValue(StorageDataKey.SettingFilterRules);
65 | if (rules != null) {
66 | List ruleList = SerializeUtil.deserializeFilterRuleList(rules);
67 | result.addAll(ruleList);
68 | } else {
69 | result.add(DefaultFilterRule);
70 | }
71 | return result;
72 | }
73 |
74 | public static boolean inFilterRule(String key, List rules) {
75 | for (FilterRule rule : rules) {
76 | switch (rule.getFilterRuleType()) {
77 | case START_WITH:
78 | if (key.startsWith(rule.getFilterString())) {
79 | return true;
80 | }
81 | break;
82 | case EQUALS:
83 | if (key.equals(rule.getFilterString())) {
84 | return true;
85 | }
86 | break;
87 | case END_WITH:
88 | if (key.endsWith(rule.getFilterString())) {
89 | return true;
90 | }
91 | break;
92 | }
93 | }
94 | return false;
95 | }
96 |
97 | public enum FilterRuleType {
98 | START_WITH("Start with"),
99 | EQUALS("Equals"),
100 | END_WITH("End with");
101 |
102 | private String displayName;
103 |
104 | FilterRuleType(String displayName) {
105 | this.displayName = displayName;
106 | }
107 |
108 | public String getDisplayName() {
109 | return displayName;
110 | }
111 |
112 | public String toString() {
113 | return getDisplayName();
114 | }
115 |
116 | public static FilterRuleType fromName(String name) {
117 | if (name == null)
118 | return START_WITH;
119 | for (FilterRuleType type : values()) {
120 | if (type.name().equals(name)) {
121 | return type;
122 | }
123 | }
124 | return START_WITH;
125 | }
126 |
127 | public String toName() {
128 | return name();
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/module/SupportedLanguages.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.module;
18 |
19 |
20 | import com.example.wujs.language_engine.TranslationEngineType;
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | /**
25 | * Created by Wesley Lin on 11/29/14.
26 | */
27 | public enum SupportedLanguages {
28 | Afrikaans("af", "Afrikaans", "Afrikaans"),
29 | Albanian("sq", "Shqiptar", "Albanian"),
30 | Arabic("ar", "العربية", "Arabic"),
31 | Azerbaijani("az", "Azərbaycan", "Azerbaijani"),
32 | Basque("eu", "Euskal", "Basque"),
33 | Bengali("bn", "বাঙালি", "Bengali"),
34 | Belarusian("be", "Беларускі", "Belarusian"),
35 | Bulgarian("bg", "Български", "Bulgarian"),
36 | Catalan("ca", "Català", "Catalan"),
37 | Chinese_Simplified("zh-CN", "简体中文", "Chinese Simplified"),
38 | Chinese_Simplified_BING("zh-CHS", "简体中文", "Chinese Simplified"),
39 | Chinese_Traditional("zh-TW", "正體中文", "Chinese Traditional"),
40 | Chinese_Traditional_BING("zh-CHT", "正體中文", "Chinese Traditional"),
41 | Croatian("hr", "Hrvatski", "Croatian"),
42 | Czech("cs", "Čeština", "Czech"),
43 | Danish("da", "Dansk", "Danish"),
44 | Dutch("nl", "Nederlands", "Dutch"),
45 | English("en", "English", "English"),
46 | Esperanto("eo", "Esperanta", "Esperanto"),
47 | Estonian("et", "Eesti", "Estonian"),
48 | Filipino("tl", "Pilipino", "Filipino"),
49 | Finnish("fi", "Suomi", "Finnish"),
50 | French("fr", "Français", "French"),
51 | Galician("gl", "Galego", "Galician"),
52 | Georgian("ka", "ქართული", "Georgian"),
53 | German("de", "Deutsch", "German"),
54 | Greek("el", "Ελληνικά", "Greek"),
55 | Gujarati("gu", "ગુજરાતી", "Gujarati"),
56 | Haitian_Creole("ht", "Haitiancreole", "Haitian Creole"),
57 | Hebrew("iw", "עברית", "Hebrew"),
58 | Hebrew_BING("he", "עברית", "Hebrew"),
59 | Hindi("hi", "हिंदी", "Hindi"),
60 | Hungarian("hu", "Magyar", "Hungarian"),
61 | Icelandic("is", "Icelandic", "Icelandic"),
62 | Indonesian("id", "Indonesia", "Indonesian"),
63 | Irish("ga", "Irish", "Irish"),
64 | Italian("it", "Italiano", "Italian"),
65 | Japanese("ja", "日本語", "Japanese"),
66 | Kannada("kn", "ಕನ್ನಡ", "Kannada"),
67 | Korean("ko", "한국의", "Korean"),
68 | Latin("la", "Latina", "Latin"),
69 | Latvian("lv", "Latvijas", "Latvian"),
70 | Lithuanian("lt", "Lietuvos", "Lithuanian"),
71 | Macedonian("mk", "Македонски", "Macedonian"),
72 | Malay("ms", "Melayu", "Malay"),
73 | Maltese("mt", "Malti", "Maltese"),
74 | Norwegian("no", "Norsk", "Norwegian"),
75 | Persian("fa", "فارسی", "Persian"),
76 | Polish("pl", "Polski", "Polish"),
77 | Portuguese("pt", "Português", "Portuguese"),
78 | Romanian("ro", "Român", "Romanian"),
79 | Russian("ru", "Русский", "Russian"),
80 | Serbian("sr", "Српски", "Serbian"),
81 | Slovak("sk", "Slovenčina", "Slovak"),
82 | Slovenian("sl", "Slovenščina", "Slovenian"),
83 | Spanish("es", "Español", "Spanish"),
84 | Swahili("sw", "Kiswahili", "Swahili"),
85 | Swedish("sv", "Svenska", "Swedish"),
86 | Tamil("ta", "தமிழ்", "Tamil"),
87 | Telugu("te", "తెలుగు", "Telugu"),
88 | Thai("th", "ไทย", "Thai"),
89 | Turkish("tr", "Türk", "Turkish"),
90 | Ukrainian("uk", "Український", "Ukrainian"),
91 | Urdu("ur", "اردو", "Urdu"),
92 | Vietnamese("vi", "Tiếng Việt", "Vietnamese"),
93 | Welsh("cy", "Cymraeg", "Welsh"),
94 | Yiddish("yi", "ייִדיש", "Yiddish"),
95 |
96 | AUTO_BAIDU("auto","自动检测","auto check"),
97 | Chinese_Simplified_BAIDU("zh", "简体中文", "Chinese Simplified","zh-rCN"),
98 | Chinese_Traditional_BAIDU("cht", "正體中文", "Chinese Traditional","zh-rTW"),
99 | English_BAIDU("en", "English", "English","en"),
100 | Japanese_BAIDU("jp","日本語","Japanese","ja"),
101 | Korean_BAIDU("kor","","Korean","ko"),
102 | French_BAIDU("fra", "Français", "French","fr"),
103 | Spanish_BAIDU("spa", "Español", "Spanish","es"),
104 | Thai_BAIDU("th", "ไทย", "Thai","th"),
105 | Arabic_BAIDU("ara", "العربية", "Arabic","ar"),
106 | Russian_BAIDU("ru", "Русский", "Russian","ru"),
107 | Portuguese_BAIDU("pt", "Português", "Portuguese","pt"),
108 | German_BAIDU("de", "Deutsch", "German","de"),
109 | Italian_BAIDU("it", "Italiano", "Italian","it"),
110 | Greek_BAIDU("el", "Ελληνικά", "Greek","el"),
111 | Dutch_BAIDU("nl", "Nederlands", "Dutch","nl"),
112 | Polish_BAIDU("pl", "Polski", "Polish","pl"),
113 | Bulgarian_BAIDU("bul", "Български", "Bulgarian","bg"),
114 | Estonian_BAIDU("est", "Eesti", "Estonian","et"),
115 | Danish_BAIDU("dan", "Dansk", "Danish","da"),
116 | Finnish_BAIDU("fin", "Suomi", "Finnish","fi"),
117 | Czech_BAIDU("cs", "Čeština", "Czech","cs"),
118 | Romanian_BAIDU("rom", "Român", "Romanian","ro"),
119 | Slovenian_BAIDU("slo", "Slovenščina", "Slovenian","sl"),
120 | Swedish_BAIDU("swe", "Svenska", "Swedish","sv"),
121 | Hungarian_BAIDU("hu", "Magyar", "Hungarian","hu"),
122 | Vietnamese_BAIDU("vie", "Tiếng Việt", "Vietnamese","vi");
123 |
124 | private String languageCode;
125 | private String languageDisplayName;
126 | private String languageEnglishDisplayName;
127 | private String realLanguageCode;
128 |
129 | SupportedLanguages(String languageCode, String languageDisplayName, String languageEnglishDisplayName) {
130 | this.languageCode = languageCode;
131 | this.languageDisplayName = languageDisplayName;
132 | this.languageEnglishDisplayName = languageEnglishDisplayName;
133 | }
134 | SupportedLanguages(String languageCode, String languageDisplayName, String languageEnglishDisplayName,String realLanguageCode) {
135 | this.languageCode = languageCode;
136 | this.languageDisplayName = languageDisplayName;
137 | this.languageEnglishDisplayName = languageEnglishDisplayName;
138 | this.realLanguageCode = realLanguageCode;
139 | }
140 | public String getLanguageCode() {
141 | return languageCode;
142 | }
143 |
144 | public String getLanguageDisplayName() {
145 | return languageDisplayName;
146 | }
147 |
148 | public String getLanguageEnglishDisplayName() {
149 | return languageEnglishDisplayName;
150 | }
151 | public String getRealLanguageCode() {
152 | return realLanguageCode;
153 | }
154 |
155 | public static List getAllSupportedLanguages(TranslationEngineType type) {
156 | switch (type) {
157 | case Baidu:
158 | return getBaiduLanguages();
159 | case Bing:
160 | return getBingLanguages();
161 | case Google:
162 | return getGoogleLanguages();
163 | }
164 | return null;
165 | }
166 |
167 | public String toString() {
168 | return getLanguageEnglishDisplayName() + "(\"" + getLanguageCode() + "\", \"" + getLanguageDisplayName() + "\")";
169 | }
170 |
171 | // get the right value-XX suffix
172 | public String getAndroidStringFolderNameSuffix() {
173 | if (this.name().contains("BAIDU")){
174 | System.out.println(this.toString());
175 | return this.getRealLanguageCode();
176 | }
177 | if (this == Chinese_Simplified_BING || this == Chinese_Simplified)
178 | return "zh-rCN";
179 | if (this == Chinese_Traditional_BING || this == Chinese_Traditional)
180 | return "zh-rTW";
181 | if (this == Hebrew_BING)
182 | return Hebrew.getLanguageCode();
183 |
184 | return this.getLanguageCode();
185 | }
186 | // google supported language code: https://cloud.google.com/translate/v2/using_rest, language reference section
187 | private static List getBaiduLanguages() {
188 | List result = new ArrayList();
189 | result.add(Chinese_Simplified_BAIDU);
190 | result.add(Chinese_Traditional_BAIDU);
191 | result.add(English_BAIDU);
192 | result.add(Japanese_BAIDU);
193 | result.add(Korean_BAIDU);
194 | result.add(French_BAIDU);
195 | result.add(Spanish_BAIDU);
196 | result.add(Thai_BAIDU);
197 | result.add(Arabic_BAIDU);
198 | result.add(Russian_BAIDU);
199 | result.add(Portuguese_BAIDU);
200 | result.add(German_BAIDU);
201 | result.add(Italian_BAIDU);
202 | result.add(Greek_BAIDU);
203 | result.add(Dutch_BAIDU);
204 | result.add(Polish_BAIDU);
205 | result.add(Bulgarian_BAIDU);
206 | result.add(Estonian_BAIDU);
207 | result.add(Danish_BAIDU);
208 | result.add(Finnish_BAIDU);
209 | result.add(Czech_BAIDU);
210 | result.add(Romanian_BAIDU);
211 | result.add(Slovenian_BAIDU);
212 | result.add(Swedish_BAIDU);
213 | result.add(Hungarian_BAIDU);
214 | result.add(Vietnamese_BAIDU);
215 | return result;
216 | }
217 | // google supported language code: https://cloud.google.com/translate/v2/using_rest, language reference section
218 | private static List getGoogleLanguages() {
219 | List result = new ArrayList();
220 | result.add(Afrikaans);
221 | result.add(Albanian);
222 | result.add(Arabic);
223 | result.add(Azerbaijani);
224 | result.add(Basque);
225 | result.add(Bengali);
226 | result.add(Belarusian);
227 | result.add(Bulgarian);
228 | result.add(Catalan);
229 | result.add(Chinese_Simplified);
230 | result.add(Chinese_Traditional);
231 | result.add(Croatian);
232 | result.add(Czech);
233 | result.add(Danish);
234 | result.add(Dutch);
235 | // result.add(English);
236 | result.add(Esperanto);
237 | result.add(Estonian);
238 | result.add(Filipino);
239 | result.add(Finnish);
240 | result.add(French);
241 | result.add(Galician);
242 | result.add(Georgian);
243 | result.add(German);
244 | result.add(Greek);
245 | result.add(Gujarati);
246 | result.add(Haitian_Creole);
247 | result.add(Hebrew);
248 | result.add(Hindi);
249 | result.add(Hungarian);
250 | result.add(Icelandic);
251 | result.add(Indonesian);
252 | result.add(Irish);
253 | result.add(Italian);
254 | result.add(Japanese);
255 | result.add(Kannada);
256 | result.add(Korean);
257 | result.add(Latin);
258 | result.add(Latvian);
259 | result.add(Macedonian);
260 | result.add(Malay);
261 | result.add(Maltese);
262 | result.add(Norwegian);
263 | result.add(Persian);
264 | result.add(Polish);
265 | result.add(Portuguese);
266 | result.add(Romanian);
267 | result.add(Russian);
268 | result.add(Serbian);
269 | result.add(Slovak);
270 | result.add(Slovenian);
271 | result.add(Spanish);
272 | result.add(Swahili);
273 | result.add(Swedish);
274 | result.add(Tamil);
275 | result.add(Telugu);
276 | result.add(Thai);
277 | result.add(Turkish);
278 | result.add(Ukrainian);
279 | result.add(Urdu);
280 | result.add(Vietnamese);
281 | result.add(Welsh);
282 | result.add(Yiddish);
283 | return result;
284 | }
285 |
286 | // bing supported language code: http://msdn.microsoft.com/en-us/library/hh456380.aspx
287 | private static List getBingLanguages() {
288 | List result = new ArrayList();
289 | result.add(Arabic);
290 | result.add(Bulgarian);
291 | result.add(Catalan);
292 | result.add(Chinese_Simplified_BING);
293 | result.add(Chinese_Traditional_BING);
294 | result.add(Czech);
295 | result.add(Danish);
296 | result.add(Dutch);
297 | result.add(English);
298 | result.add(Estonian);
299 | result.add(Finnish);
300 | result.add(French);
301 | result.add(German);
302 | result.add(Greek);
303 | result.add(Haitian_Creole);
304 | result.add(Hebrew_BING);
305 | result.add(Hindi);
306 | result.add(Hungarian);
307 | result.add(Indonesian);
308 | result.add(Italian);
309 | result.add(Japanese);
310 | result.add(Korean);
311 | result.add(Latvian);
312 | result.add(Lithuanian);
313 | result.add(Malay);
314 | result.add(Maltese);
315 | result.add(Norwegian);
316 | result.add(Persian);
317 | result.add(Polish);
318 | result.add(Portuguese);
319 | result.add(Romanian);
320 | result.add(Russian);
321 | result.add(Slovak);
322 | result.add(Slovenian);
323 | result.add(Spanish);
324 | result.add(Swedish);
325 | result.add(Thai);
326 | result.add(Turkish);
327 | result.add(Ukrainian);
328 | result.add(Urdu);
329 | result.add(Vietnamese);
330 | result.add(Welsh);
331 | return result;
332 | }
333 | }
334 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/settings/SettingConfigurable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.settings;
18 |
19 | import com.example.wujs.data.Log;
20 | import com.example.wujs.data.SerializeUtil;
21 | import com.example.wujs.data.StorageDataKey;
22 | import com.example.wujs.language_engine.TranslationEngineType;
23 | import com.example.wujs.module.FilterRule;
24 | import com.example.wujs.ui.AddFilterRuleDialog;
25 | import com.example.wujs.ui.GoogleAlertDialog;
26 | import com.intellij.ide.util.PropertiesComponent;
27 | import com.intellij.openapi.options.Configurable;
28 | import com.intellij.openapi.options.ConfigurationException;
29 | import com.intellij.openapi.ui.ComboBox;
30 | import com.intellij.ui.components.JBList;
31 | import com.intellij.ui.components.JBScrollPane;
32 | import org.jdesktop.swingx.VerticalLayout;
33 | import org.jdesktop.swingx.prompt.PromptSupport;
34 | import org.jetbrains.annotations.Nls;
35 | import org.jetbrains.annotations.Nullable;
36 |
37 | import javax.swing.*;
38 | import java.awt.*;
39 | import java.awt.event.ActionEvent;
40 | import java.awt.event.ActionListener;
41 | import java.awt.event.MouseAdapter;
42 | import java.awt.event.MouseEvent;
43 | import java.io.IOException;
44 | import java.net.URI;
45 | import java.net.URISyntaxException;
46 | import java.util.ArrayList;
47 |
48 | /**
49 | * Created by Wesley Lin on 12/8/14.
50 | */
51 | public class SettingConfigurable implements Configurable, ActionListener {
52 |
53 | private static final String DEFAULT_CLIENT_ID = "Default client id";
54 | private static final String DEFAULT_CLIENT_SECRET = "Default client secret";
55 | private static final String DEFAULT_BAIDU_APPID_PROMPT = "Please input your Baidu APP ID";
56 | private static final String DEFAULT_BAIDU_KEY_PROMPT = "Please input your Baidu SecretKey";
57 |
58 | private static final String DEFAULT_GOOGLE_API_KEY = "Enter API key here";
59 |
60 | private static final String BING_HOW_TO = "How to get ClientId and ClientSecret?";
61 | private static final String BAIDU_HOW_TO = "How to get APP ID and SecretKey?";
62 |
63 | private MouseAdapter baiduHowTo = new MouseAdapter() {
64 | @Override
65 | public void mouseClicked(MouseEvent e) {
66 | try {
67 | Desktop.getDesktop().browse(new URI("http://api.fanyi.baidu.com/api/trans/product/index"));
68 | } catch (URISyntaxException | IOException e1) {
69 | e1.printStackTrace();
70 | }
71 | }
72 | };
73 | private MouseAdapter bingHowTo = new MouseAdapter() {
74 | @Override
75 | public void mouseClicked(MouseEvent e) {
76 | try {
77 | Desktop.getDesktop().browse(new URI("http://blogs.msdn.com/b/translation/p/gettingstarted1.aspx"));
78 | } catch (URISyntaxException | IOException e1) {
79 | e1.printStackTrace();
80 | }
81 | }
82 | };
83 |
84 | private static final String GOOGLE_HOW_TO = "How to set up Google Translation API key?";
85 | private MouseAdapter googleHowTo = new MouseAdapter() {
86 | @Override
87 | public void mouseClicked(MouseEvent e) {
88 | try {
89 | Desktop.getDesktop().browse(new URI("https://cloud.google.com/translate/v2/getting_started#intro"));
90 | } catch (URISyntaxException | IOException e1) {
91 | e1.printStackTrace();
92 | }
93 | }
94 | };
95 |
96 | private JPanel settingPanel;
97 | private JComboBox languageEngineBox;
98 | private TranslationEngineType currentEngine;
99 |
100 | private JLabel howToLabel;
101 | private JLabel line1Text;
102 | private JTextField line1TextField;
103 | private JLabel line2Text;
104 | private JTextField line2TextField;
105 |
106 | private JBList filterList;
107 | private JButton btnAddFilter;
108 | private JButton btnDeleteFilter;
109 |
110 | private java.util.List filterRules = new ArrayList();
111 | private boolean languageEngineChanged = false;
112 | private boolean filterRulesChanged = false;
113 |
114 | @Nls
115 | @Override
116 | public String getDisplayName() {
117 | return "AndroidTranslation";
118 | }
119 |
120 | @Nullable
121 | @Override
122 | public String getHelpTopic() {
123 | return getDisplayName();
124 | }
125 |
126 | @Nullable
127 | @Override
128 | public JComponent createComponent() {
129 | if (settingPanel == null) {
130 | settingPanel = new JPanel(new VerticalLayout(18));
131 |
132 | // header UI
133 | Container container = new Container();
134 | container.setLayout(new BorderLayout());
135 |
136 | currentEngine = TranslationEngineType.fromName(
137 | PropertiesComponent.getInstance().getValue(StorageDataKey.SettingLanguageEngine));
138 | TranslationEngineType[] items = TranslationEngineType.getLanguageEngineArray();
139 | languageEngineBox = new ComboBox(items);
140 | languageEngineBox.setEnabled(true);
141 | languageEngineBox.setSelectedItem(currentEngine);
142 | languageEngineBox.addActionListener(this);
143 |
144 | container.add(new JLabel("Language engine: "), BorderLayout.WEST);
145 | container.add(languageEngineBox, BorderLayout.CENTER);
146 |
147 | settingPanel.add(container);
148 |
149 | initContentContainer();
150 | initAndAddFilterContainer();
151 | }
152 | return settingPanel;
153 | }
154 |
155 | @Override
156 | public boolean isModified() {
157 | if (languageEngineChanged)
158 | return true;
159 |
160 | if (filterRulesChanged)
161 | return true;
162 |
163 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
164 | switch (currentEngine) {
165 | case Baidu:
166 | String baiduClientIdStored = propertiesComponent.getValue(StorageDataKey.BaiduClientIdStored);
167 | String baiduClientSecretStored = propertiesComponent.getValue(StorageDataKey.BaiduClientSecretStored);
168 |
169 | boolean baiduClientIdChanged = false;
170 | boolean baiduClientSecretChanged = false;
171 | if (baiduClientIdStored == null) {
172 | if (!line1TextField.getText().isEmpty())
173 | baiduClientIdChanged = true;
174 | } else {
175 | if (!line1TextField.getText().equals(baiduClientIdStored)
176 | && !line1TextField.getText().trim().isEmpty())
177 | baiduClientIdChanged = true;
178 | }
179 |
180 | if (baiduClientSecretStored == null) {
181 | if (!line2TextField.getText().isEmpty())
182 | baiduClientSecretChanged = true;
183 | } else {
184 | if (!line2TextField.getText().equals(baiduClientSecretStored)
185 | && !line2TextField.getText().trim().isEmpty())
186 | baiduClientSecretChanged = true;
187 | }
188 | return baiduClientIdChanged || baiduClientSecretChanged;
189 | case Bing: {
190 | String bingClientIdStored = propertiesComponent.getValue(StorageDataKey.BingClientIdStored);
191 | String bingClientSecretStored = propertiesComponent.getValue(StorageDataKey.BingClientSecretStored);
192 |
193 | boolean bingClientIdChanged = false;
194 | boolean bingClientSecretChanged = false;
195 |
196 | if (bingClientIdStored == null) {
197 | if (!line1TextField.getText().isEmpty())
198 | bingClientIdChanged = true;
199 | } else {
200 | if (!line1TextField.getText().equals(bingClientIdStored)
201 | && !line1TextField.getText().trim().isEmpty())
202 | bingClientIdChanged = true;
203 | }
204 |
205 | if (bingClientSecretStored == null) {
206 | if (!line2TextField.getText().isEmpty())
207 | bingClientSecretChanged = true;
208 | } else {
209 | if (!line2TextField.getText().equals(bingClientSecretStored)
210 | && !line2TextField.getText().trim().isEmpty())
211 | bingClientSecretChanged = true;
212 | }
213 |
214 | return bingClientIdChanged || bingClientSecretChanged;
215 | }
216 | case Google: {
217 | String googleApiKeyStored = propertiesComponent.getValue(StorageDataKey.GoogleApiKeyStored);
218 | boolean googleApiKeyStoredChanged = false;
219 |
220 | if (googleApiKeyStored == null) {
221 | if (!line1TextField.getText().isEmpty())
222 | googleApiKeyStoredChanged = true;
223 | } else {
224 | if (!line1TextField.getText().equals(googleApiKeyStored)
225 | && !line1TextField.getText().trim().isEmpty())
226 | googleApiKeyStoredChanged = true;
227 | }
228 | return googleApiKeyStoredChanged;
229 | }
230 | }
231 | return false;
232 | }
233 |
234 | @Override
235 | public void apply() throws ConfigurationException {
236 | Log.i("apply clicked");
237 | if (languageEngineBox == null || filterList == null
238 | || btnAddFilter == null || btnDeleteFilter == null
239 | || line1TextField == null || line2TextField == null)
240 | return;
241 |
242 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
243 |
244 | languageEngineChanged = false;
245 | propertiesComponent.setValue(StorageDataKey.SettingLanguageEngine, currentEngine.toName());
246 |
247 | switch (currentEngine) {
248 | case Baidu:
249 | if (!line1TextField.getText().trim().isEmpty()) {
250 | propertiesComponent.setValue(StorageDataKey.BaiduClientIdStored, line1TextField.getText());
251 | PromptSupport.setPrompt(line1TextField.getText(), line1TextField);
252 | }
253 |
254 | if (!line2TextField.getText().trim().isEmpty()) {
255 | propertiesComponent.setValue(StorageDataKey.BaiduClientSecretStored, line2TextField.getText());
256 | PromptSupport.setPrompt(line2TextField.getText(), line2TextField);
257 | }
258 | line1TextField.setText("");
259 | line2TextField.setText("");
260 | break;
261 | case Bing: {
262 | if (!line1TextField.getText().trim().isEmpty()) {
263 | propertiesComponent.setValue(StorageDataKey.BingClientIdStored, line1TextField.getText());
264 | PromptSupport.setPrompt(line1TextField.getText(), line1TextField);
265 | }
266 |
267 | if (!line2TextField.getText().trim().isEmpty()) {
268 | propertiesComponent.setValue(StorageDataKey.BingClientSecretStored, line2TextField.getText());
269 | PromptSupport.setPrompt(line2TextField.getText(), line2TextField);
270 | }
271 | line1TextField.setText("");
272 | line2TextField.setText("");
273 | }
274 | break;
275 | case Google: {
276 | if (!line1TextField.getText().trim().isEmpty()) {
277 | propertiesComponent.setValue(StorageDataKey.GoogleApiKeyStored, line1TextField.getText());
278 | PromptSupport.setPrompt(line1TextField.getText(), line1TextField);
279 | }
280 | line1TextField.setText("");
281 | }
282 | break;
283 | }
284 | languageEngineBox.requestFocus();
285 |
286 | filterRulesChanged = false;
287 | propertiesComponent.setValue(StorageDataKey.SettingFilterRules,
288 | SerializeUtil.serializeFilterRuleList(filterRules));
289 | }
290 |
291 | @Override
292 | public void reset() {
293 | if (settingPanel == null || languageEngineBox == null || filterList == null
294 | || btnAddFilter == null || btnDeleteFilter == null)
295 | return;
296 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
297 |
298 | currentEngine = TranslationEngineType.fromName(
299 | propertiesComponent.getValue(StorageDataKey.SettingLanguageEngine));
300 | languageEngineBox.setSelectedItem(currentEngine);
301 | languageEngineChanged = false;
302 | initUI(currentEngine);
303 |
304 | Log.i("reset, current engine: " + currentEngine);
305 |
306 | languageEngineBox.requestFocus();
307 |
308 | // filter rules
309 | filterRulesChanged = false;
310 | resetFilterList();
311 | }
312 |
313 | @Override
314 | public void disposeUIResources() {
315 |
316 | }
317 |
318 | @Override
319 | public void actionPerformed(ActionEvent e) {
320 | JComboBox comboBox = (JComboBox) e.getSource();
321 | TranslationEngineType type = (TranslationEngineType) comboBox.getSelectedItem();
322 | if ((type == currentEngine) && (!languageEngineChanged))
323 | return;
324 |
325 | languageEngineChanged = true;
326 | Log.i("selected type: " + type.name());
327 | currentEngine = type;
328 |
329 | initUI(currentEngine);
330 |
331 | // default: false, if user set 'never show', set true
332 | boolean GoogleAlertMsgShownSetting = PropertiesComponent.getInstance().getBoolean(StorageDataKey.GoogleAlertMsgShownSetting, false);
333 | if (currentEngine == TranslationEngineType.Google && !GoogleAlertMsgShownSetting) {
334 | new GoogleAlertDialog(settingPanel, false).show();
335 | }
336 | }
337 |
338 | private void initUI(TranslationEngineType engineType) {
339 | if (settingPanel == null)
340 | return;
341 |
342 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
343 | switch (engineType) {
344 | case Baidu: {
345 | line1Text.setText("APP ID:");
346 | line2Text.setText("SecretKey:");
347 | line2Text.setVisible(true);
348 | line2TextField.setVisible(true);
349 | howToLabel.setText(BAIDU_HOW_TO);
350 | howToLabel.removeMouseMotionListener(googleHowTo);
351 | howToLabel.removeMouseMotionListener(bingHowTo);
352 | howToLabel.addMouseListener(baiduHowTo);
353 |
354 | String baiduClientIdStored = propertiesComponent.getValue(StorageDataKey.BaiduClientIdStored);
355 | String baiduClientSecretStored = propertiesComponent.getValue(StorageDataKey.BaiduClientSecretStored);
356 |
357 | if (baiduClientIdStored != null) {
358 | PromptSupport.setPrompt(baiduClientIdStored, line1TextField);
359 | } else {
360 | PromptSupport.setPrompt(DEFAULT_BAIDU_APPID_PROMPT, line1TextField);
361 | }
362 | line1TextField.setText("");
363 |
364 | if (baiduClientSecretStored != null) {
365 | PromptSupport.setPrompt(baiduClientSecretStored, line2TextField);
366 | } else {
367 | PromptSupport.setPrompt(DEFAULT_BAIDU_KEY_PROMPT, line2TextField);
368 | }
369 | line2TextField.setText("");
370 | }
371 | break;
372 | case Bing: {
373 | line1Text.setText("Client Id:");
374 | line2Text.setText("Client secret:");
375 | line2Text.setVisible(true);
376 |
377 | line2TextField.setVisible(true);
378 |
379 | howToLabel.setText(BING_HOW_TO);
380 | howToLabel.removeMouseMotionListener(googleHowTo);
381 | howToLabel.removeMouseMotionListener(baiduHowTo);
382 | howToLabel.addMouseListener(bingHowTo);
383 |
384 | String bingClientIdStored = propertiesComponent.getValue(StorageDataKey.BingClientIdStored);
385 | String bingClientSecretStored = propertiesComponent.getValue(StorageDataKey.BingClientSecretStored);
386 |
387 | if (bingClientIdStored != null) {
388 | PromptSupport.setPrompt(bingClientIdStored, line1TextField);
389 | } else {
390 | PromptSupport.setPrompt(DEFAULT_CLIENT_ID, line1TextField);
391 | }
392 | line1TextField.setText("");
393 |
394 | if (bingClientSecretStored != null) {
395 | PromptSupport.setPrompt(bingClientSecretStored, line2TextField);
396 | } else {
397 | PromptSupport.setPrompt(DEFAULT_CLIENT_SECRET, line2TextField);
398 | }
399 | line2TextField.setText("");
400 | }
401 | break;
402 | case Google: {
403 | line1Text.setText("API key:");
404 | line2Text.setVisible(false);
405 |
406 | line2TextField.setVisible(false);
407 |
408 | howToLabel.setText(GOOGLE_HOW_TO);
409 | howToLabel.removeMouseMotionListener(bingHowTo);
410 | howToLabel.removeMouseMotionListener(baiduHowTo);
411 | howToLabel.addMouseListener(googleHowTo);
412 |
413 | String googleAPIKey = propertiesComponent.getValue(StorageDataKey.GoogleApiKeyStored);
414 |
415 | if (googleAPIKey != null) {
416 | PromptSupport.setPrompt(googleAPIKey, line1TextField);
417 | } else {
418 | PromptSupport.setPrompt(DEFAULT_GOOGLE_API_KEY, line1TextField);
419 | }
420 | line1TextField.setText("");
421 | }
422 | break;
423 | }
424 | }
425 |
426 | private void initContentContainer() {
427 | line1TextField = new JTextField();
428 | line2TextField = new JTextField();
429 |
430 | line1Text = new JLabel("Client Id:");
431 | line2Text = new JLabel("Client Secret:");
432 |
433 | Container outContainer = new Container();
434 | outContainer.setLayout(new BorderLayout(0, 5));
435 |
436 | howToLabel = new JLabel();
437 | howToLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
438 | outContainer.add(howToLabel, BorderLayout.NORTH);
439 |
440 | Container contentContainer = new Container();
441 | contentContainer.setLayout(new GridBagLayout());
442 | ((GridBagLayout) contentContainer.getLayout()).columnWidths = new int[]{0, 0, 0};
443 | ((GridBagLayout) contentContainer.getLayout()).rowHeights = new int[]{0, 0, 0};
444 | ((GridBagLayout) contentContainer.getLayout()).columnWeights = new double[]{0.0, 0.0, 1.0E-4};
445 | ((GridBagLayout) contentContainer.getLayout()).rowWeights = new double[]{0.0, 0.0, 1.0E-4};
446 |
447 | line1Text.setHorizontalAlignment(SwingConstants.RIGHT);
448 | contentContainer.add(line1Text, new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0,
449 | GridBagConstraints.CENTER, GridBagConstraints.BOTH,
450 | new Insets(0, 0, 5, 5), 0, 0));
451 |
452 | contentContainer.add(line1TextField, new GridBagConstraints(1, 0, 1, 1, 10.0, 0.0,
453 | GridBagConstraints.CENTER, GridBagConstraints.BOTH,
454 | new Insets(0, 0, 5, 0), 0, 0));
455 |
456 | line2Text.setHorizontalAlignment(SwingConstants.RIGHT);
457 | contentContainer.add(line2Text, new GridBagConstraints(0, 1, 1, 1, 0.5, 0.0,
458 | GridBagConstraints.CENTER, GridBagConstraints.BOTH,
459 | new Insets(0, 0, 0, 5), 0, 0));
460 | contentContainer.add(line2TextField, new GridBagConstraints(1, 1, 1, 1, 10.0, 0.0,
461 | GridBagConstraints.CENTER, GridBagConstraints.BOTH,
462 | new Insets(0, 0, 0, 0), 0, 0));
463 |
464 | outContainer.add(contentContainer, BorderLayout.CENTER);
465 | settingPanel.add(outContainer);
466 | }
467 |
468 | private void initAndAddFilterContainer() {
469 | Container filterSettingContainer = new Container();
470 | filterSettingContainer.setLayout(new BorderLayout(0, 5));
471 |
472 | final JLabel filterLabel = new JLabel("Filter setting");
473 | filterSettingContainer.add(filterLabel, BorderLayout.NORTH);
474 |
475 | Container listPane = new Container();
476 | listPane.setLayout(new BorderLayout());
477 |
478 | JBScrollPane scrollPane = new JBScrollPane();
479 | filterList = new JBList(new String[]{"1,", "2"});
480 |
481 | filterList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
482 | scrollPane.setViewportView(filterList);
483 | listPane.add(scrollPane, BorderLayout.NORTH);
484 |
485 | Container btnPane = new Container();
486 | btnPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
487 | btnAddFilter = new JButton("+");
488 | btnDeleteFilter = new JButton("-");
489 | btnPane.add(btnAddFilter);
490 | btnPane.add(btnDeleteFilter);
491 |
492 | filterList.addMouseListener(new MouseAdapter() {
493 | @Override
494 | public void mouseClicked(MouseEvent e) {
495 | if (SwingUtilities.isLeftMouseButton(e)) {
496 | if (filterList.getSelectedIndex() <= 0) {
497 | btnDeleteFilter.setEnabled(false);
498 | } else {
499 | btnDeleteFilter.setEnabled(true);
500 | }
501 | }
502 | }
503 | });
504 |
505 | btnAddFilter.addActionListener(new ActionListener() {
506 | @Override
507 | public void actionPerformed(ActionEvent actionEvent) {
508 | filterRulesChanged = true;
509 | AddFilterRuleDialog dialog = new AddFilterRuleDialog(settingPanel,
510 | "Set your filter rule", false);
511 | dialog.setOnOKClickedListener(new AddFilterRuleDialog.OnOKClickedListener() {
512 | @Override
513 | public void onClick(FilterRule.FilterRuleType ruleType, String filterNameString) {
514 | filterRules.add(new FilterRule(ruleType, filterNameString));
515 | int index = filterList.getSelectedIndex();
516 | filterList.setListData(getFilterRulesDisplayString());
517 | filterList.setSelectedIndex(index);
518 | }
519 | });
520 | dialog.show();
521 | }
522 | });
523 |
524 | btnDeleteFilter.addActionListener(new ActionListener() {
525 | @Override
526 | public void actionPerformed(ActionEvent actionEvent) {
527 | filterRulesChanged = true;
528 | int index = filterList.getSelectedIndex();
529 | filterRules.remove(index);
530 | filterList.setListData(getFilterRulesDisplayString());
531 | if (index < filterRules.size()) {
532 | filterList.setSelectedIndex(index);
533 | } else {
534 | if (filterRules.size() == 1) {
535 | btnDeleteFilter.setEnabled(false);
536 | }
537 | filterList.setSelectedIndex(filterRules.size() - 1);
538 | }
539 | }
540 | });
541 |
542 | listPane.add(btnPane, BorderLayout.CENTER);
543 | filterSettingContainer.add(listPane, BorderLayout.CENTER);
544 |
545 | settingPanel.add(filterSettingContainer);
546 | }
547 |
548 | private void resetFilterList() {
549 | btnDeleteFilter.setEnabled(false);
550 | filterRules.clear();
551 | filterRules.addAll(FilterRule.getFilterRulesFromLocal());
552 |
553 | filterList.setListData(getFilterRulesDisplayString());
554 | }
555 |
556 | private String[] getFilterRulesDisplayString() {
557 | String[] displayStrings = new String[filterRules.size()];
558 | for (int i = 0; i < filterRules.size(); i++) {
559 | displayStrings[i] = filterRules.get(i).toString();
560 | }
561 | return displayStrings;
562 | }
563 | }
564 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/ui/AddFilterRuleDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.ui;
18 |
19 | import com.example.wujs.module.FilterRule;
20 | import com.intellij.openapi.application.ModalityState;
21 | import com.intellij.openapi.ui.ComboBox;
22 | import com.intellij.openapi.ui.DialogWrapper;
23 | import com.intellij.openapi.ui.Messages;
24 | import com.intellij.openapi.util.Computable;
25 | import com.intellij.openapi.util.SystemInfo;
26 | import com.intellij.openapi.wm.IdeFrame;
27 | import com.intellij.openapi.wm.WindowManager;
28 | import com.intellij.ui.mac.foundation.MacUtil;
29 | import com.intellij.util.Alarm;
30 | import org.jdesktop.swingx.prompt.PromptSupport;
31 | import org.jetbrains.annotations.NotNull;
32 | import org.jetbrains.annotations.Nullable;
33 |
34 | import javax.swing.*;
35 | import java.awt.*;
36 | import java.lang.reflect.Method;
37 | import java.util.concurrent.atomic.AtomicInteger;
38 |
39 | /**
40 | * Created by Wesley Lin on 12/15/14.
41 | */
42 | public class AddFilterRuleDialog extends DialogWrapper {
43 |
44 | public interface OnOKClickedListener {
45 | public void onClick(FilterRule.FilterRuleType ruleType, String filterNameString);
46 | }
47 |
48 | private MyBorderLayout myLayout;
49 | private ComboBox ruleType;
50 | private JTextField filterName;
51 |
52 | private OnOKClickedListener onOKClickedListener;
53 |
54 | public void setOnOKClickedListener(OnOKClickedListener onOKClickedListener) {
55 | this.onOKClickedListener = onOKClickedListener;
56 | }
57 |
58 | public AddFilterRuleDialog(@Nullable Component parent,
59 | String title,
60 | boolean canBeParent) {
61 | super(parent, canBeParent);
62 | _init(title, null);
63 | }
64 |
65 | protected void _init(String title,
66 | @Nullable DoNotAskOption doNotAskOption) {
67 | setTitle(title);
68 | if (Messages.isMacSheetEmulation()) {
69 | setUndecorated(true);
70 | }
71 |
72 | setButtonsAlignment(SwingConstants.RIGHT);
73 | setDoNotAskOption(doNotAskOption);
74 | init();
75 | if (Messages.isMacSheetEmulation()) {
76 | MacUtil.adjustFocusTraversal(myDisposable);
77 | }
78 | }
79 |
80 | @Override
81 | protected void doOKAction() {
82 | super.doOKAction();
83 | if (onOKClickedListener != null && ruleType != null && filterName != null) {
84 | onOKClickedListener.onClick((FilterRule.FilterRuleType) ruleType.getSelectedItem(),
85 | filterName.getText());
86 | }
87 | }
88 |
89 | @NotNull
90 | @Override
91 | protected Action[] createActions() {
92 | Action[] actions;
93 | if (SystemInfo.isMac) {
94 | actions = new Action[]{myCancelAction, myOKAction};
95 | } else {
96 | actions = new Action[]{myOKAction, myCancelAction};
97 | }
98 | return actions;
99 | }
100 |
101 | @Override
102 | public void doCancelAction() {
103 | close(-1);
104 | }
105 |
106 | @Override
107 | protected JComponent createCenterPanel() {
108 | return doCreateCenterPanel();
109 | }
110 |
111 | @NotNull
112 | public LayoutManager createRootLayout() {
113 | return Messages.isMacSheetEmulation() ? myLayout = new MyBorderLayout() : new BorderLayout();
114 | }
115 |
116 | @Override
117 | protected void dispose() {
118 | if (Messages.isMacSheetEmulation()) {
119 | animate();
120 | } else {
121 | super.dispose();
122 | }
123 | }
124 |
125 | @Override
126 | public void show() {
127 | if (Messages.isMacSheetEmulation()) {
128 | setInitialLocationCallback(new Computable() {
129 | @Override
130 | public Point compute() {
131 | JRootPane rootPane = SwingUtilities.getRootPane(getWindow().getParent());
132 | if (rootPane == null) {
133 | rootPane = SwingUtilities.getRootPane(getWindow().getOwner());
134 | }
135 |
136 | Point p = rootPane.getLocationOnScreen();
137 | p.x += (rootPane.getWidth() - getWindow().getWidth()) / 2;
138 | return p;
139 | }
140 | });
141 | animate();
142 | if (SystemInfo.isJavaVersionAtLeast("1.7")) {
143 | try {
144 | Method method = Class.forName("java.awt.Window").getDeclaredMethod("setOpacity", float.class);
145 | if (method != null) method.invoke(getPeer().getWindow(), .8f);
146 | } catch (Exception exception) {
147 | }
148 | }
149 | setAutoAdjustable(false);
150 | setSize(getPreferredSize().width, 0);//initial state before animation, zero height
151 | }
152 | super.show();
153 | }
154 |
155 | private void animate() {
156 | final int height = getPreferredSize().height;
157 | final int frameCount = 10;
158 | final boolean toClose = isShowing();
159 |
160 |
161 | final AtomicInteger i = new AtomicInteger(-1);
162 | final Alarm animator = new Alarm(myDisposable);
163 | final Runnable runnable = new Runnable() {
164 | @Override
165 | public void run() {
166 | int state = i.addAndGet(1);
167 |
168 | double linearProgress = (double) state / frameCount;
169 | if (toClose) {
170 | linearProgress = 1 - linearProgress;
171 | }
172 | myLayout.myPhase = (1 - Math.cos(Math.PI * linearProgress)) / 2;
173 | Window window = getPeer().getWindow();
174 | Rectangle bounds = window.getBounds();
175 | bounds.height = (int) (height * myLayout.myPhase);
176 |
177 | window.setBounds(bounds);
178 |
179 | if (state == 0 && !toClose && window.getOwner() instanceof IdeFrame) {
180 | WindowManager.getInstance().requestUserAttention((IdeFrame) window.getOwner(), true);
181 | }
182 |
183 | if (state < frameCount) {
184 | animator.addRequest(this, 10);
185 | } else if (toClose) {
186 | AddFilterRuleDialog.super.dispose();
187 | }
188 | }
189 | };
190 | animator.addRequest(runnable, 10, ModalityState.stateForComponent(getRootPane()));
191 | }
192 |
193 | protected JComponent doCreateCenterPanel() {
194 | JPanel panel = new JPanel(new BorderLayout(5, 0));
195 |
196 | FilterRule.FilterRuleType[] types = FilterRule.FilterRuleType.values();
197 |
198 | ruleType = new ComboBox(types);
199 | ruleType.setEnabled(true);
200 | ruleType.setSelectedIndex(0);
201 |
202 | panel.add(ruleType, BorderLayout.WEST);
203 |
204 | filterName = new JTextField(20);
205 | PromptSupport.setPrompt("Set the string name here", filterName);
206 | panel.add(filterName, BorderLayout.CENTER);
207 |
208 | return panel;
209 | }
210 |
211 | @Override
212 | protected void doHelpAction() {
213 | // do nothing
214 | }
215 |
216 | private static class MyBorderLayout extends BorderLayout {
217 | private double myPhase = 0;//it varies from 0 (hidden state) to 1 (fully visible)
218 |
219 | private MyBorderLayout() {
220 | }
221 |
222 | @Override
223 | public void layoutContainer(Container target) {
224 | final Dimension realSize = target.getSize();
225 | target.setSize(target.getPreferredSize());
226 |
227 | super.layoutContainer(target);
228 |
229 | target.setSize(realSize);
230 |
231 | synchronized (target.getTreeLock()) {
232 | int yShift = (int) ((1 - myPhase) * target.getPreferredSize().height);
233 | Component[] components = target.getComponents();
234 | for (Component component : components) {
235 | Point point = component.getLocation();
236 | point.y -= yShift;
237 | component.setLocation(point);
238 | }
239 | }
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/ui/GoogleAlertDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.ui;
18 |
19 | import com.example.wujs.data.StorageDataKey;
20 | import com.intellij.ide.util.PropertiesComponent;
21 | import com.intellij.openapi.ui.DialogWrapper;
22 | import com.intellij.openapi.ui.Messages;
23 | import com.intellij.openapi.util.SystemInfo;
24 | import com.intellij.ui.ScrollPaneFactory;
25 | import com.intellij.ui.mac.foundation.MacUtil;
26 | import com.intellij.util.ui.UIUtil;
27 | import org.jetbrains.annotations.NotNull;
28 | import org.jetbrains.annotations.Nullable;
29 |
30 | import javax.swing.*;
31 | import java.awt.*;
32 | import java.awt.event.ActionEvent;
33 | import java.io.IOException;
34 | import java.net.URI;
35 | import java.net.URISyntaxException;
36 |
37 | /**
38 | * Created by Wesley Lin on 12/27/14.
39 | */
40 | public class GoogleAlertDialog extends DialogWrapper {
41 |
42 | private String mMessage;
43 |
44 | public GoogleAlertDialog(@Nullable Component parent,
45 | boolean canBeParent) {
46 | super(parent, canBeParent);
47 | _init("Information", "Google Translate API is a paid service. The pricing is based on usage. Translation usage is calculated in millions of characters (M), where 1 M = 106 characters");
48 | }
49 |
50 | protected void _init(String title, String message) {
51 | setTitle(title);
52 | mMessage = message;
53 | if (Messages.isMacSheetEmulation()) {
54 | setUndecorated(true);
55 | }
56 |
57 | setButtonsAlignment(SwingConstants.RIGHT);
58 | setDoNotAskOption(null);
59 | init();
60 | if (Messages.isMacSheetEmulation()) {
61 | MacUtil.adjustFocusTraversal(myDisposable);
62 | }
63 | }
64 |
65 | private Action detailAction = new AbstractAction(UIUtil.replaceMnemonicAmpersand("Pricing details")) {
66 | @Override
67 | public void actionPerformed(ActionEvent e) {
68 | try {
69 | Desktop.getDesktop().browse(new URI("https://cloud.google.com/translate/v2/pricing"));
70 | } catch (URISyntaxException e1) {
71 | e1.printStackTrace();
72 | } catch (IOException e1) {
73 | e1.printStackTrace();
74 | }
75 | close(5, true);
76 | }
77 | };
78 |
79 | private Action neverShowAction = new AbstractAction(UIUtil.replaceMnemonicAmpersand("Never show this again")) {
80 | @Override
81 | public void actionPerformed(ActionEvent e) {
82 | PropertiesComponent.getInstance().setValue(StorageDataKey.GoogleAlertMsgShownSetting, String.valueOf(true));
83 | close(6, true);
84 | }
85 | };
86 |
87 | @NotNull
88 | @Override
89 | protected Action[] createActions() {
90 | Action[] actions;
91 | if (SystemInfo.isMac) {
92 | actions = new Action[]{myCancelAction, neverShowAction, detailAction, myOKAction};
93 | } else {
94 | actions = new Action[]{myOKAction, detailAction, neverShowAction, myCancelAction};
95 | }
96 | return actions;
97 | }
98 |
99 | @Nullable
100 | @Override
101 | protected JComponent createCenterPanel() {
102 | JPanel panel = new JPanel(new BorderLayout(15, 0));
103 |
104 | // icon
105 | JLabel iconLabel = new JLabel(Messages.getInformationIcon());
106 | Container container = new Container();
107 | container.setLayout(new BorderLayout());
108 | container.add(iconLabel, BorderLayout.NORTH);
109 | panel.add(container, BorderLayout.WEST);
110 |
111 | if (mMessage != null) {
112 | final JTextPane messageComponent = MultiSelectDialog.createMessageComponent(mMessage);
113 |
114 | final Dimension screenSize = messageComponent.getToolkit().getScreenSize();
115 | final Dimension textSize = messageComponent.getPreferredSize();
116 | if (mMessage.length() > 100) {
117 | final JScrollPane pane = ScrollPaneFactory.createScrollPane(messageComponent);
118 | pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
119 | pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
120 | pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
121 | final int scrollSize = (int) new JScrollBar(Adjustable.VERTICAL).getPreferredSize().getWidth();
122 | final Dimension preferredSize =
123 | new Dimension(Math.min(textSize.width, screenSize.width / 2) + scrollSize,
124 | Math.min(textSize.height, screenSize.height / 3) + scrollSize);
125 | pane.setPreferredSize(preferredSize);
126 | panel.add(pane, BorderLayout.CENTER);
127 | } else {
128 | panel.add(messageComponent, BorderLayout.CENTER);
129 | }
130 | }
131 | return panel;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/ui/MultiSelectDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2015 Wesley Lin
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.wujs.ui;
18 |
19 | import com.example.wujs.data.StorageDataKey;
20 | import com.example.wujs.language_engine.TranslationEngineType;
21 | import com.example.wujs.module.SupportedLanguages;
22 | import com.intellij.ide.util.PropertiesComponent;
23 | import com.intellij.openapi.application.ModalityState;
24 | import com.intellij.openapi.project.Project;
25 | import com.intellij.openapi.ui.DialogWrapper;
26 | import com.intellij.openapi.ui.Messages;
27 | import com.intellij.openapi.util.Computable;
28 | import com.intellij.openapi.util.SystemInfo;
29 | import com.intellij.openapi.wm.IdeFrame;
30 | import com.intellij.openapi.wm.WindowManager;
31 | import com.intellij.ui.BrowserHyperlinkListener;
32 | import com.intellij.ui.ScrollPaneFactory;
33 | import com.intellij.ui.mac.foundation.MacUtil;
34 | import com.intellij.util.Alarm;
35 | import com.intellij.util.ui.UIUtil;
36 | import org.jetbrains.annotations.NotNull;
37 | import org.jetbrains.annotations.Nullable;
38 |
39 | import javax.swing.*;
40 | import javax.swing.plaf.basic.BasicHTML;
41 | import javax.swing.text.html.HTMLEditorKit;
42 | import java.awt.*;
43 | import java.awt.event.ItemEvent;
44 | import java.awt.event.ItemListener;
45 | import java.lang.reflect.Method;
46 | import java.util.ArrayList;
47 | import java.util.List;
48 | import java.util.concurrent.atomic.AtomicInteger;
49 |
50 | /**
51 | * Created by Wesley Lin on 11/29/14.
52 | */
53 | public class MultiSelectDialog extends DialogWrapper {
54 |
55 | public static final double GOLDEN_RATIO = 0.618;
56 | public static final double REVERSE_GOLDEN_RATIO = 1 - GOLDEN_RATIO;
57 |
58 | public interface OnOKClickedListener {
59 | public void onClick(List selectedLanguages, boolean overrideChecked);
60 | }
61 |
62 | private PropertiesComponent propertiesComponent;
63 | protected String myMessage;
64 | private MyBorderLayout myLayout;
65 |
66 | private JCheckBox myCheckBox;
67 | private String myCheckboxText;
68 | private boolean myChecked;
69 |
70 | private java.util.List data;
71 | private java.util.List selectedLanguages = new ArrayList();
72 | private OnOKClickedListener onOKClickedListener;
73 |
74 | public void setOnOKClickedListener(OnOKClickedListener onOKClickedListener) {
75 | this.onOKClickedListener = onOKClickedListener;
76 | }
77 |
78 | public MultiSelectDialog(@Nullable Project project,
79 | String message,
80 | String title,
81 | @Nullable String checkboxText,
82 | boolean checkboxStatus,
83 | TranslationEngineType translationEngineType,
84 | boolean canBeParent) {
85 | super(project, canBeParent);
86 | data = SupportedLanguages.getAllSupportedLanguages(translationEngineType);
87 | _init(project, title, message, checkboxText, checkboxStatus, null);
88 | }
89 |
90 | protected void _init(Project project,
91 | String title,
92 | String message,
93 | @Nullable String checkboxText,
94 | boolean checkboxStatus,
95 | @Nullable DoNotAskOption doNotAskOption) {
96 | setTitle(title);
97 | if (Messages.isMacSheetEmulation()) {
98 | setUndecorated(true);
99 | }
100 | propertiesComponent = PropertiesComponent.getInstance(project);
101 | myMessage = message;
102 | myCheckboxText = checkboxText;
103 | myChecked = checkboxStatus;
104 | setButtonsAlignment(SwingConstants.RIGHT);
105 | setDoNotAskOption(doNotAskOption);
106 | init();
107 | if (Messages.isMacSheetEmulation()) {
108 | MacUtil.adjustFocusTraversal(myDisposable);
109 | }
110 | }
111 |
112 | @Override
113 | protected void doOKAction() {
114 | super.doOKAction();
115 | if (onOKClickedListener != null) {
116 | onOKClickedListener.onClick(selectedLanguages, myCheckBox.isSelected());
117 | }
118 | }
119 |
120 | @NotNull
121 | @Override
122 | protected Action[] createActions() {
123 | Action[] actions;
124 | if (SystemInfo.isMac) {
125 | actions = new Action[]{myCancelAction, myOKAction};
126 | } else {
127 | actions = new Action[]{myOKAction, myCancelAction};
128 | }
129 | return actions;
130 | }
131 |
132 | @Override
133 | public void doCancelAction() {
134 | close(-1);
135 | }
136 |
137 | @Override
138 | protected JComponent createCenterPanel() {
139 | return doCreateCenterPanel();
140 | }
141 |
142 | @NotNull
143 | public LayoutManager createRootLayout() {
144 | return Messages.isMacSheetEmulation() ? myLayout = new MyBorderLayout() : new BorderLayout();
145 | }
146 |
147 | @Override
148 | protected void dispose() {
149 | if (Messages.isMacSheetEmulation()) {
150 | animate();
151 | } else {
152 | super.dispose();
153 | }
154 | }
155 |
156 | @Override
157 | public void show() {
158 | if (Messages.isMacSheetEmulation()) {
159 | setInitialLocationCallback(new Computable() {
160 | @Override
161 | public Point compute() {
162 | JRootPane rootPane = SwingUtilities.getRootPane(getWindow().getParent());
163 | if (rootPane == null) {
164 | rootPane = SwingUtilities.getRootPane(getWindow().getOwner());
165 | }
166 |
167 | Point p = rootPane.getLocationOnScreen();
168 | p.x += (rootPane.getWidth() - getWindow().getWidth()) / 2;
169 | return p;
170 | }
171 | });
172 | animate();
173 | if (SystemInfo.isJavaVersionAtLeast("1.7")) {
174 | try {
175 | Method method = Class.forName("java.awt.Window").getDeclaredMethod("setOpacity", float.class);
176 | if (method != null) method.invoke(getPeer().getWindow(), .8f);
177 | } catch (Exception exception) {
178 | }
179 | }
180 | setAutoAdjustable(false);
181 | setSize(getPreferredSize().width, 0);//initial state before animation, zero height
182 | }
183 | super.show();
184 | }
185 |
186 | private void animate() {
187 | final int height = getPreferredSize().height;
188 | final int frameCount = 10;
189 | final boolean toClose = isShowing();
190 |
191 |
192 | final AtomicInteger i = new AtomicInteger(-1);
193 | final Alarm animator = new Alarm(myDisposable);
194 | final Runnable runnable = new Runnable() {
195 | @Override
196 | public void run() {
197 | int state = i.addAndGet(1);
198 |
199 | double linearProgress = (double) state / frameCount;
200 | if (toClose) {
201 | linearProgress = 1 - linearProgress;
202 | }
203 | myLayout.myPhase = (1 - Math.cos(Math.PI * linearProgress)) / 2;
204 | Window window = getPeer().getWindow();
205 | Rectangle bounds = window.getBounds();
206 | bounds.height = (int) (height * myLayout.myPhase);
207 |
208 | window.setBounds(bounds);
209 |
210 | if (state == 0 && !toClose && window.getOwner() instanceof IdeFrame) {
211 | WindowManager.getInstance().requestUserAttention((IdeFrame) window.getOwner(), true);
212 | }
213 |
214 | if (state < frameCount) {
215 | animator.addRequest(this, 10);
216 | } else if (toClose) {
217 | MultiSelectDialog.super.dispose();
218 | }
219 | }
220 | };
221 | animator.addRequest(runnable, 10, ModalityState.stateForComponent(getRootPane()));
222 | }
223 |
224 | protected JComponent doCreateCenterPanel() {
225 | final JPanel panel = new JPanel(new BorderLayout(15, 0));
226 |
227 | /*if (myMessage != null) {
228 | final JTextPane messageComponent = createMessageComponent(myMessage);
229 |
230 | final Dimension screenSize = messageComponent.getToolkit().getScreenSize();
231 | final Dimension textSize = messageComponent.getPreferredSize();
232 | if (myMessage.length() > 100) {
233 | final JScrollPane pane = ScrollPaneFactory.createScrollPane(messageComponent);
234 | pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
235 | pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
236 | pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
237 | final int scrollSize = (int) new JScrollBar(Adjustable.VERTICAL).getPreferredSize().getWidth() + 12;
238 | final Dimension preferredSize =
239 | new Dimension(Math.min(textSize.width, (int) (screenSize.width * REVERSE_GOLDEN_RATIO)) + scrollSize,
240 | Math.min(textSize.height, screenSize.height / 3) + scrollSize);
241 | pane.setPreferredSize(preferredSize);
242 | panel.add(pane, BorderLayout.NORTH);
243 | } else {
244 | panel.add(messageComponent, BorderLayout.NORTH);
245 | }
246 | }*/
247 |
248 | if (!data.isEmpty()) {
249 | final Container container = new Container();
250 |
251 | final JCheckBox checkbox_selectAll = new JCheckBox("Select All");
252 | checkbox_selectAll.setMargin(new Insets(22, 300, 0, 0));
253 | panel.add(checkbox_selectAll, BorderLayout.NORTH);
254 |
255 | checkbox_selectAll.addItemListener(new ItemListener() {
256 | @Override
257 | public void itemStateChanged(ItemEvent e) {
258 | if (e.getStateChange() == ItemEvent.SELECTED) {
259 | selectedLanguages.addAll(data);
260 | checkbox_selectAll.setSelected(true);
261 |
262 | for(Component component:container.getComponents()){
263 | JCheckBox checkBox = (JCheckBox) component;
264 | checkBox.setSelected(true);
265 | }
266 |
267 | } else if (e.getStateChange() == ItemEvent.DESELECTED) {
268 | checkbox_selectAll.setSelected(false);
269 | selectedLanguages.removeAll(data);
270 |
271 | for(Component component:container.getComponents()){
272 | JCheckBox checkBox = (JCheckBox) component;
273 | checkBox.setSelected(false);
274 | }
275 | }
276 | }
277 | });
278 |
279 |
280 | int gridCol = 3;
281 | int gridRow = (data.size() % gridCol == 0) ? data.size() / gridCol : data.size() / gridCol + 1;
282 | container.setLayout(new GridLayout(gridRow, gridCol));
283 | for (final SupportedLanguages language : data) {
284 | JCheckBox checkbox = new JCheckBox(language.getLanguageEnglishDisplayName()
285 | + " (" + language.getLanguageDisplayName() + ") ");
286 | checkbox.addItemListener(new ItemListener() {
287 | @Override
288 | public void itemStateChanged(ItemEvent e) {
289 | if (e.getStateChange() == ItemEvent.SELECTED) {
290 | if (!selectedLanguages.contains(language)) {
291 | selectedLanguages.add(language);
292 | }
293 | } else if (e.getStateChange() == ItemEvent.DESELECTED) {
294 | if (selectedLanguages.contains(language)) {
295 | selectedLanguages.remove(language);
296 | }
297 | }
298 | }
299 | });
300 | checkbox.setSelected(
301 | propertiesComponent.getBoolean(
302 | StorageDataKey.SupportedLanguageCheckStatusPrefix + language.getLanguageCode(), false));
303 | container.add(checkbox);
304 | }
305 |
306 | panel.add(container, BorderLayout.CENTER);
307 | }
308 |
309 | if (myCheckboxText != null) {
310 |
311 | myCheckBox = new JCheckBox(myCheckboxText);
312 | myCheckBox.setSelected(myChecked);
313 | myCheckBox.setMargin(new Insets(2, -4, 0, 0));
314 |
315 | panel.add(myCheckBox, BorderLayout.SOUTH);
316 | }
317 |
318 | return panel;
319 | }
320 |
321 | protected static JTextPane createMessageComponent(final String message) {
322 | final JTextPane messageComponent = new JTextPane();
323 | return configureMessagePaneUi(messageComponent, message);
324 | }
325 |
326 | @Override
327 | protected void doHelpAction() {
328 | // do nothing
329 | }
330 |
331 | @NotNull
332 | public static JTextPane configureMessagePaneUi(JTextPane messageComponent, String message) {
333 | return configureMessagePaneUi(messageComponent, message, true);
334 | }
335 |
336 | @NotNull
337 | public static JTextPane configureMessagePaneUi(JTextPane messageComponent,
338 | String message,
339 | final boolean addBrowserHyperlinkListener) {
340 | messageComponent.setFont(UIUtil.getLabelFont());
341 | if (BasicHTML.isHTMLString(message)) {
342 | final HTMLEditorKit editorKit = new HTMLEditorKit();
343 | editorKit.getStyleSheet().addRule(UIUtil.displayPropertiesToCSS(UIUtil.getLabelFont(), UIUtil.getLabelForeground()));
344 | messageComponent.setEditorKit(editorKit);
345 | messageComponent.setContentType(UIUtil.HTML_MIME);
346 | if (addBrowserHyperlinkListener) {
347 | messageComponent.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
348 | }
349 | }
350 | messageComponent.setText(message);
351 | messageComponent.setEditable(false);
352 | if (messageComponent.getCaret() != null) {
353 | messageComponent.setCaretPosition(0);
354 | }
355 |
356 | if (UIUtil.isUnderNimbusLookAndFeel()) {
357 | messageComponent.setOpaque(false);
358 | messageComponent.setBackground(UIUtil.TRANSPARENT_COLOR);
359 | } else {
360 | messageComponent.setBackground(UIUtil.getOptionPaneBackground());
361 | }
362 |
363 | messageComponent.setForeground(UIUtil.getLabelForeground());
364 | return messageComponent;
365 | }
366 |
367 | private static class MyBorderLayout extends BorderLayout {
368 | private double myPhase = 0;//it varies from 0 (hidden state) to 1 (fully visible)
369 |
370 | private MyBorderLayout() {
371 | }
372 |
373 | @Override
374 | public void layoutContainer(Container target) {
375 | final Dimension realSize = target.getSize();
376 | target.setSize(target.getPreferredSize());
377 |
378 | super.layoutContainer(target);
379 |
380 | target.setSize(realSize);
381 |
382 | synchronized (target.getTreeLock()) {
383 | int yShift = (int) ((1 - myPhase) * target.getPreferredSize().height);
384 | Component[] components = target.getComponents();
385 | for (Component component : components) {
386 | Point point = component.getLocation();
387 | point.y -= yShift;
388 | component.setLocation(point);
389 | }
390 | }
391 | }
392 | }
393 | }
394 |
--------------------------------------------------------------------------------
/src/main/java/com/example/wujs/util/Logger.java:
--------------------------------------------------------------------------------
1 | package com.example.wujs.util;
2 |
3 |
4 | import com.intellij.notification.*;
5 |
6 | /**
7 | * create on 17/12/16
8 | * @author wujs
9 | */
10 | public class Logger {
11 | private static String NAME;
12 | private static int LEVEL = 0;
13 |
14 | public static final int DEBUG = 3;
15 | public static final int INFO = 2;
16 | public static final int WARN = 1;
17 | public static final int ERROR = 0;
18 |
19 | public static void init(String name,int level) {
20 | NAME = name;
21 | LEVEL = level;
22 | NotificationsConfiguration.getNotificationsConfiguration().register(NAME, NotificationDisplayType.NONE);
23 | }
24 |
25 | public static void debug(String text) {
26 | if (LEVEL >= DEBUG) {
27 | Notifications.Bus.notify(
28 | new Notification(NAME, NAME + " [DEBUG]", text, NotificationType.INFORMATION));
29 | }
30 | }
31 |
32 | public static void info(String text) {
33 | if (LEVEL > INFO) {
34 | Notifications.Bus.notify(
35 | new Notification(NAME, NAME + " [INFO]", text, NotificationType.INFORMATION));
36 | }
37 | }
38 |
39 | public static void warn(String text) {
40 | if (LEVEL > WARN) {
41 | Notifications.Bus.notify(
42 | new Notification(NAME, NAME + " [WARN]", text, NotificationType.WARNING));
43 | }
44 | }
45 |
46 | public static void error(String text) {
47 | if (LEVEL > ERROR) {
48 | Notifications.Bus.notify(
49 | new Notification(NAME, NAME + " [ERROR]", text, NotificationType.ERROR));
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | org.example.wujushan.AndroidLocalizationer
3 | Android Localizationer
4 | wujushan
5 |
6 | string resources(e.g. strings.xml) to your target languages automactically.
8 | Help developers localize their Android app easily, with just one click.
9 | Use multiple Translation APIs to translate strings into other languages.
10 | .
11 | ]]>
12 |
13 |
15 | com.intellij.modules.platform
16 | com.intellij.modules.lang
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/icons/globe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wujushan/AndroidLocalizationer/ba646217218c2209aab437961f672bc503215e94/src/main/resources/icons/globe.png
--------------------------------------------------------------------------------
/src/main/resources/icons/globe@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wujushan/AndroidLocalizationer/ba646217218c2209aab437961f672bc503215e94/src/main/resources/icons/globe@2x.png
--------------------------------------------------------------------------------
/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | VDforTwit
3 | Default Folder
4 | Video Download
5 | Download
6 | MyVideos
7 | No Data
8 | Load failed, Please retry
9 | Default Folder
10 | No Data
11 | Click download button for download
12 | Disclaimer
13 | Cancel
14 | More Operation
15 | Rename
16 | Delete
17 | Move to Other Folder
18 | Save to Alum
19 | Saved
20 | Share
21 | Choose Folder
22 | No Memery
23 | All Select
24 | Download Quene
25 | DownLoad Failed,Please check network
26 | Cancel All
27 | Paused
28 | Waiting...
29 | DownLoad Failed
30 | Downloading...
31 | Import album
32 | Download from Network
33 | Importing
34 | Waiting...
35 | Default folder Not Delete
36 | Tips
37 | Are you sure you want to delete this folder and all the files it contains?
38 | Confirm
39 | Deleting
40 | Name of Folder
41 | Input
42 | File Already Exist
43 | Folder Already Exist
44 | Are you sure you want to delete this video?
45 | General \n Before accepting the VideoDownloader service, be sure to read this clause carefully and agree to this statement. \n The direct use of the VideoDownloader service and data by the user, either directly or through various means, shall be deemed to have accepted the entire contents of this statement unconditionally; if the user has any objection to any of the terms stated in this statement, please discontinue the use of the VideoDownloader All services. \n \n the first \n users in a variety of ways to use the VideoDownloader service in the process, not in any way using VideoDownloader directly or indirectly in violation of Chinese law, and social morality behavior. \n \n second \nVideoDownloader only to provide users with mobile video storage management services, through the built-in browser can search for video, VideoDownloader does not save any video to the server, all the video is stored locally in the phone. Video saved from the network is downloaded by the user, and the VideoDownloader only provides services from the cache to the stored service. User use of the video VideoDownloader do not know, need to be responsible for the preservation of the video, such as all disputes caused by the user to bear all the legal and joint responsibility. VideoDownloader does not assume any legal and joint liability. VideoDownloader does not assume any liability for any reason why you are unable to use the VideoDownloader for any reason, such as network conditions, communication lines, third party websites, or regulatory requirements.
46 | All video
47 | No videos
48 | You can share and cache videos from the following sites
49 | Input link
50 | Do not worry, the page is being loaded, it may be slow or need to hang VPN
51 | Downloading background , please go to my video later
52 | Find video
53 | Found the video, is it downloaded now?
54 | Get video
55 | Click the play button
56 | Due to youtube related policies can not be downloaded
57 | Unable to download video, Please Authorization me
58 | Enter the link below\nthe upper right button to view the progress of the download\nAfter the download is complete\n you can go to the first page of my video view
59 | How to use
60 |
61 | \n 1. Click the platform On the home page.\n\n 2. Login it Click the video Play button you want to download.\n\n 3. then click to download button on Bottom right corner\n\n Important: Which video you want to download must click on its play button in advance. Super simple!!
62 |
63 |
64 | App lock
65 | Feedback
66 | Protect your privacy
67 | Check update
68 | Rate us
69 | Setting
70 | mailto:guangyue944@gmail.com
71 | VideoDownloader Feedback
72 | Sorry, you need to install the mail client
73 | Set your password to protect your privacy
74 | Do not use a third-party keyboard when entering a password
75 | Modify password
76 | password setting
77 | Please enter the password you want to set
78 | password setting
79 | Authentication
80 | Please enter your original password
81 | Please enter the password you want to set
82 | The password you entered twice is different. Please re-enter it
83 | Sorry your original password is wrong, please re-enter
84 | Sorry your password is wrong, please re-enter it
85 | Please confirm your new password
86 | Password set up successfully, the next time you start the application to take effect!
87 | The password is on and will take effect the next time the app is launched
88 | Unlocked successfully
89 | View progress
90 | Search
91 | Notifications
92 | Setting
93 | open
94 | close
95 | NavaActivity
96 |
97 | Section 1
98 | Section 2
99 | Section 3
100 |
101 | Open navigation drawer
102 | Close navigation drawer
103 |
104 | Example action
105 |
106 | Settings
107 | MainActivity
108 | search
109 | download queue
110 | App Lock
111 | Rate Us
112 | exit
113 | sure exit this page?
114 | Cruel refuse
115 | Praise
116 | Comment
117 | Can you give praise?
118 | Permission
119 | Reject permission will not be able to use the software.Reset it?
120 | download_sites
121 | How many stars do you want to evaluate??
122 | complete
123 | Press again to exit
124 | Recommend
125 | I developed a more powerful application than this can download all online HD videos
126 | You have already downloaded 5 videos. Is this worth a 5-star rating?
127 | downloaded
128 | downloading
129 | Parsing Url
130 | As shown in the video above there will be a download button
131 |
132 |
133 |
--------------------------------------------------------------------------------