├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── README.md
├── _config.yml
├── build.gradle
├── csv.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── groovy-app.iml
├── gui.png
├── ide-plugin
├── build.gradle
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── pandawarrior
│ │ └── androidXMLConverter
│ │ ├── GUI.form
│ │ ├── GUI.java
│ │ └── XMLsToCSV.java
│ └── resources
│ └── META-INF
│ └── plugin.xml
├── javafx_gui
├── build.gradle
├── javafx_gui.iml
└── src
│ └── main
│ ├── groovy
│ └── org
│ │ └── pandawarrior
│ │ ├── App.groovy
│ │ └── Controller.groovy
│ └── resources
│ └── fxml
│ └── app.fxml
├── settings.gradle
├── strings.png
└── xml_csv_parse
├── build.gradle
├── src
└── main
│ └── groovy
│ └── org
│ └── pandawarrior
│ ├── ReadXml.groovy
│ └── WriteXml.groovy
└── xml_csv_parse.iml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Java template
3 | *.class
4 |
5 | # Mobile Tools for Java (J2ME)
6 | .mtj.tmp/
7 |
8 | # Package Files #
9 | *.jar
10 | *.war
11 | *.ear
12 |
13 | ### JetBrains template
14 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion
15 |
16 | *.iml
17 |
18 | ## Directory-based project format:
19 | .idea/
20 | # if you remove the above rule, at least ignore the following:
21 |
22 | # User-specific stuff:
23 | # .idea/workspace.xml
24 | # .idea/tasks.xml
25 | # .idea/dictionaries
26 |
27 | # Sensitive or high-churn files:
28 | # .idea/dataSources.ids
29 | # .idea/dataSources.xml
30 | # .idea/sqlDataSources.xml
31 | # .idea/dynamic.xml
32 | # .idea/uiDesigner.xml
33 |
34 | # Gradle:
35 | # .idea/gradle.xml
36 | # .idea/libraries
37 |
38 | # Mongo Explorer plugin:
39 | # .idea/mongoSettings.xml
40 |
41 | ## File-based project format:
42 | *.ipr
43 | *.iws
44 |
45 | ## Plugin-specific files:
46 |
47 | # IntelliJ
48 | /out/
49 |
50 | # mpeltonen/sbt-idea plugin
51 | .idea_modules/
52 |
53 | # JIRA plugin
54 | atlassian-ide-plugin.xml
55 |
56 | # Crashlytics plugin (for Android Studio and IntelliJ)
57 | com_crashlytics_export_strings.xml
58 | crashlytics.properties
59 | crashlytics-build.properties
60 |
61 |
62 |
63 | ### Gradle template
64 | .gradle
65 | build/
66 |
67 | # Ignore Gradle GUI config
68 | gradle-app.setting
69 |
70 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
71 | !gradle-wrapper.jar
72 |
73 |
74 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Kotlin-XML-CSV-Parser"]
2 | path = Kotlin-XML-CSV-Parser
3 | url = git@github.com:LiewJunTung/Kotlin-XML-CSV-Parser.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | notifications:
3 | email:
4 | - pandawarrior91@gmail.com
5 | jdk:
6 | - oraclejdk8
7 | git:
8 | submodules: false
9 | before_install:
10 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
11 | - git submodule update --init --recursive
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Liew Jun Tung
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android String XML-CSV Converter
2 | [](https://travis-ci.org/pandawarrior91/Android-strings-xml-csv-converter)
3 |
4 | ## Status
5 | I have written a better [library](https://github.com/LiewJunTung/Kotlin-XML-CSV-Parser) to handle conversion between CSV and XML and back using SQLite and OpenCSV.
6 | It enables users to translate even more words and less prone to errors.
7 |
8 | ## What does it do?
9 | #### It will convert strings.xml, arrays.xml, plurals.xml
10 | 
11 | #### to CSV
12 | 
13 | #### and back!
14 |
15 | ## Why?
16 | You want to translate strings, arrays, plurals in strings.xml, arrays.xml, and plurals.xml into different
17 | languages in csv so you can use as spreadsheet in Excel, Google Drive
18 |
19 | ## Requirement
20 | Java JRE 8
21 | or
22 | Jetbrains IDE
23 |
24 | ## How to use it?
25 | 1. Download the file
26 | * [groovy-app.zip](https://github.com/pandawarrior91/Android-strings-xml-csv-converter/releases/download/v0.10.0/groovy-app.zip)
27 | * [groovy-app.tar](https://github.com/pandawarrior91/Android-strings-xml-csv-converter/releases/download/v0.10.0/groovy-app.tar)
28 | 2. Unzip or untar the file
29 | 3. Open groovy-app/bin/groovy-app (groovy-app.bat if you are on Windows)
30 | 4. From here, with the GUI onwards it's pretty self explanatory. Select Android folder for the value and the location of your saved csv.
31 |
32 | 
33 |
34 | ### OR
35 | Download and install the IntelliJ or Android Studio Plugin from the jetbrains repository or [here](https://github.com/pandawarrior91/Android-strings-xml-csv-converter/releases/download/v0.10.0/android.xml.csv.parser.plugin.zip)
36 |
37 | ## TODO
38 | - [x] Ability to convert arrays and plurals
39 | - [x] IntelliJ and Android Studio plugin
40 | - [x] Enable the application to run in Java version less than 8
41 | - [x] Added support for commas
42 | - [ ] Clean up the (very ugly) codes (in progress)
43 | - [ ] Google Sheets Integration
44 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-hacker
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This build file was auto generated by running the Gradle 'init' task
3 | * by 'jt' at '5/9/15 2:07 PM' with Gradle 2.4
4 | *
5 | * This generated file contains a commented-out sample Java project to get you started.
6 | * For more details take a look at the Java Quickstart chapter in the Gradle
7 | * user guide available at http://gradle.org/docs/2.4/userguide/tutorial_java_projects.html
8 | */
9 |
10 | allprojects {
11 | repositories {
12 | mavenCentral()
13 | mavenLocal()
14 | }
15 | apply plugin: 'groovy'
16 | sourceCompatibility = 1.6
17 | targetCompatibility = 1.6
18 | }
--------------------------------------------------------------------------------
/csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiewJunTung/Android-strings-xml-csv-converter/554369bdceb28869043e8e8bef2522b61fd1ffbf/csv.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiewJunTung/Android-strings-xml-csv-converter/554369bdceb28869043e8e8bef2522b61fd1ffbf/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 12 10:46:40 MYT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/groovy-app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/gui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiewJunTung/Android-strings-xml-csv-converter/554369bdceb28869043e8e8bef2522b61fd1ffbf/gui.png
--------------------------------------------------------------------------------
/ide-plugin/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' }
4 | }
5 | }
6 |
7 | plugins {
8 | id "org.jetbrains.intellij" version "0.2.10"
9 | }
10 |
11 | dependencies {
12 | compile project(':Kotlin-XML-CSV-Parser')
13 | }
--------------------------------------------------------------------------------
/ide-plugin/src/main/java/org/pandawarrior/androidXMLConverter/GUI.form:
--------------------------------------------------------------------------------
1 |
2 |
239 |
--------------------------------------------------------------------------------
/ide-plugin/src/main/java/org/pandawarrior/androidXMLConverter/GUI.java:
--------------------------------------------------------------------------------
1 | package org.pandawarrior.androidXMLConverter;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.ui.DialogWrapper;
5 | import com.intellij.ui.JBColor;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 | import org.pandawarrior.app.CSVToXMLKt;
9 | import org.pandawarrior.app.TranslationType;
10 | import org.pandawarrior.app.XMLToCSVKt;
11 |
12 | import javax.swing.*;
13 | import javax.swing.filechooser.FileNameExtensionFilter;
14 | import java.awt.event.ActionEvent;
15 | import java.awt.event.ActionListener;
16 | import java.io.File;
17 |
18 | /**
19 | * Created by jt on 5/13/15.
20 | */
21 | public class GUI extends DialogWrapper {
22 |
23 | private JPanel rootPane;
24 | private JTabbedPane tabbedPane1;
25 | private JTextField xcReadField;
26 | private JTextField xcWriteField;
27 | private JButton xcWriteBtn;
28 | private JButton xcReadBtn;
29 | private JButton xcOKButton;
30 | private JButton cxReadBtn;
31 | private JButton cxWriteBtn;
32 | private JTextField cxReadField;
33 | private JTextField cxWriteField;
34 | private JButton cxOKButton;
35 | private JLabel xcLabel;
36 | private JLabel cxLabel;
37 | private JRadioButton stringsXmlRadioButton;
38 | private JRadioButton pluralsXmlRadioButton;
39 | private JRadioButton arraysXmlRadioButton;
40 | private String currentFolder;
41 | private String selected;
42 | private final static String ERROR_MSG1 = "Error! ";
43 |
44 | public GUI(Project project, String initialFolder) {
45 | super(project, true);
46 | this.setTitle("Android Parser");
47 | this.setSize(480, 300);
48 | this.setResizable(true);
49 | // setContentPane(rootPane);
50 | // setVisible(true);
51 | //setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
52 | currentFolder = initialFolder;
53 |
54 | xcReadField.setText(currentFolder);
55 | xcReadBtn.addActionListener(new ActionListener() {
56 | @Override
57 | public void actionPerformed(ActionEvent e) {
58 | String folder = chooseFolder();
59 | if (folder != null)
60 | xcReadField.setText(folder);
61 | }
62 | });
63 | xcWriteBtn.addActionListener(new ActionListener() {
64 | @Override
65 | public void actionPerformed(ActionEvent e) {
66 | String folder = chooseFolder();
67 | if (folder != null)
68 | xcWriteField.setText(folder);
69 | }
70 | });
71 | xcOKButton.addActionListener(new ActionListener() {
72 | @Override
73 | public void actionPerformed(ActionEvent e) {
74 | String folder = xcReadField.getText();
75 | String csv = xcWriteField.getText();
76 | writeCSV(folder, csv);
77 | }
78 | });
79 | cxReadBtn.addActionListener(new ActionListener() {
80 | @Override
81 | public void actionPerformed(ActionEvent e) {
82 | String csv = chooseCSV();
83 | if (csv != null)
84 | cxReadField.setText(csv);
85 | }
86 | });
87 | cxWriteBtn.addActionListener(new ActionListener() {
88 | @Override
89 | public void actionPerformed(ActionEvent e) {
90 | String folder = chooseFolder();
91 | if (folder != null)
92 | cxWriteField.setText(folder);
93 | }
94 | });
95 | cxOKButton.addActionListener(new ActionListener() {
96 | @Override
97 | public void actionPerformed(ActionEvent e) {
98 |
99 | String csv = cxReadField.getText();
100 | String folder = cxWriteField.getText();
101 | writeXML(folder, csv);
102 |
103 | }
104 | });
105 | stringsXmlRadioButton.setSelected(true);
106 | selected = "strings.xml";
107 | stringsXmlRadioButton.addActionListener(new ActionListener() {
108 | @Override
109 | public void actionPerformed(ActionEvent e) {
110 | selected = "strings.xml";
111 | }
112 | });
113 | pluralsXmlRadioButton.addActionListener(new ActionListener() {
114 | @Override
115 | public void actionPerformed(ActionEvent e) {
116 | selected = "plurals.xml";
117 | }
118 | });
119 | arraysXmlRadioButton.addActionListener(new ActionListener() {
120 | @Override
121 | public void actionPerformed(ActionEvent e) {
122 | selected = "arrays.xml";
123 | }
124 | });
125 | this.setOKActionEnabled(false);
126 | this.init();
127 |
128 | }
129 |
130 | private String chooseFolder() {
131 | JFileChooser jFileChooser = new JFileChooser();
132 | jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
133 | int returnVal = jFileChooser.showOpenDialog(getContentPane());
134 | if (returnVal == JFileChooser.APPROVE_OPTION) {
135 | return jFileChooser.getSelectedFile().getAbsolutePath();
136 | } else {
137 | return null;
138 | }
139 | }
140 |
141 | private String saveCSV() {
142 | JFileChooser jFileChooser = new JFileChooser();
143 | FileNameExtensionFilter filter = new FileNameExtensionFilter("CSV FILES", "csv", "comma separate value");
144 | jFileChooser.setFileFilter(filter);
145 | jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
146 | File file = new File(currentFolder + "/untitled.txt");
147 | jFileChooser.setCurrentDirectory(file);
148 | int returnVal = jFileChooser.showSaveDialog(getContentPanel());
149 | if (returnVal == JFileChooser.APPROVE_OPTION) {
150 | return jFileChooser.getSelectedFile().getAbsolutePath();
151 | } else {
152 | return null;
153 | }
154 | }
155 |
156 | private String chooseCSV() {
157 | JFileChooser jFileChooser = new JFileChooser();
158 | FileNameExtensionFilter filter = new FileNameExtensionFilter("CSV FILES", "csv", "comma separate value");
159 | jFileChooser.setFileFilter(filter);
160 | jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
161 | int returnVal = jFileChooser.showOpenDialog(getContentPane());
162 | if (returnVal == JFileChooser.APPROVE_OPTION) {
163 | return jFileChooser.getSelectedFile().getAbsolutePath();
164 | } else {
165 | return null;
166 | }
167 | }
168 |
169 | private void writeXML(final String folder, final String csv) {
170 | SwingUtilities.invokeLater(new Runnable() {
171 | @Override
172 | public void run() {
173 | try {
174 | if (selected.equals("strings.xml")) {
175 | //WriteXml.parse(csv, folder);
176 | CSVToXMLKt.processCSVToXML(csv, folder, TranslationType.NORMAL);
177 | } else if (selected.equals("arrays.xml")) {
178 | CSVToXMLKt.processCSVToXML(csv, folder, TranslationType.ARRAYS);
179 | // WriteXml.parseArray(csv, folder, WriteXml.getARRAY_FILE());
180 | } else if (selected.equals("plurals.xml")) {
181 | CSVToXMLKt.processCSVToXML(csv, folder, TranslationType.PLURALS);
182 | // WriteXml.parseArray(csv, folder, WriteXml.getPLURALS_FILE());
183 | }
184 | cxReadField.setText("");
185 | cxWriteField.setText("");
186 | cxLabel.setText("SUCCESS!");
187 | cxLabel.setForeground(JBColor.GREEN);
188 | } catch (ArrayIndexOutOfBoundsException e1) {
189 | cxLabel.setText(ERROR_MSG1 + e1.getMessage());
190 | cxLabel.setForeground(JBColor.RED);
191 | }
192 |
193 | }
194 | });
195 |
196 | }
197 |
198 | private void writeCSV(final String folder, final String csv) throws ArrayIndexOutOfBoundsException {
199 | SwingUtilities.invokeLater(new Runnable() {
200 | @Override
201 | public void run() {
202 | try {
203 | XMLToCSVKt.processXMLToCSV(folder, csv, TranslationType.NORMAL);
204 | XMLToCSVKt.processXMLToCSV(folder, csv, TranslationType.ARRAYS);
205 | XMLToCSVKt.processXMLToCSV(folder, csv, TranslationType.PLURALS);
206 | xcReadField.setText("");
207 | xcLabel.setText("SUCCESS!");
208 | xcLabel.setForeground(JBColor.GREEN);
209 | } catch (Exception e) {
210 | xcLabel.setText(ERROR_MSG1 + e.getMessage());
211 | xcLabel.setForeground(JBColor.RED);
212 | }
213 |
214 | }
215 | });
216 |
217 | }
218 |
219 | @Nullable
220 | @Override
221 | protected JComponent createCenterPanel() {
222 | return this.rootPane;
223 | }
224 |
225 | @NotNull
226 | protected Action[] createActions() {
227 | return new Action[0];
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/ide-plugin/src/main/java/org/pandawarrior/androidXMLConverter/XMLsToCSV.java:
--------------------------------------------------------------------------------
1 | package org.pandawarrior.androidXMLConverter;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.DataKeys;
6 | import com.intellij.openapi.project.Project;
7 |
8 | /**
9 | * Created by jt on 5/12/15.
10 | */
11 | public class XMLsToCSV extends AnAction {
12 | public void actionPerformed(AnActionEvent event) {
13 | final Project project = DataKeys.PROJECT.getData(event.getDataContext());
14 | if (project == null){
15 | return;
16 | }
17 | final String initialFolder = project.getBasePath();
18 | GUI gui = new GUI(project, initialFolder);
19 | gui.show();
20 | }
21 |
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ide-plugin/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | com.pandawarrior.androidXMLConverter
3 | Android Strings.xml To CSV Converter
4 | 2.0.1
5 | Liew Jun Tung
6 |
7 | Android XML to CSV converter.
9 | Allows you to translate strings.xml, arrays.xml, plurals.xml into different languages in spreadsheet form, and vice versa.
10 | NOTE
11 | You can access the plugin from the "Tools" menu at the IDE toolbar
12 |
13 | Changelog
14 |
15 | 2.0.1
16 | Support more rows of data
17 | Bug fixes and improves stability
18 | GitHub
19 | ]]>
20 |
21 |
22 |
23 | com.intellij.modules.lang
24 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/javafx_gui/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This build file was auto generated by running the Gradle 'init' task
3 | * by 'jt' at '5/9/15 2:07 PM' with Gradle 2.4
4 | *
5 | * This generated file contains a commented-out sample Java project to get you started.
6 | * For more details take a look at the Java Quickstart chapter in the Gradle
7 | * user guide available at http://gradle.org/docs/2.4/userguide/tutorial_java_projects.html
8 | */
9 |
10 | apply plugin: 'application'
11 | apply plugin: 'groovy'
12 |
13 |
14 | run {
15 | mainClassName = "org.pandawarrior.App"
16 | }
17 |
18 | jar {
19 | manifest {
20 | attributes "Main-Class": "$mainClassName"
21 | }
22 |
23 | from {
24 | configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
25 | }
26 | }
27 |
28 | // In this section you declare the dependencies for your production and test code
29 | dependencies {
30 | compile project(':Kotlin-XML-CSV-Parser')
31 | compile 'org.codehaus.groovy:groovy-all:2.4.10'
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/javafx_gui/javafx_gui.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/javafx_gui/src/main/groovy/org/pandawarrior/App.groovy:
--------------------------------------------------------------------------------
1 | package org.pandawarrior
2 |
3 | import javafx.application.Application
4 | import javafx.fxml.FXMLLoader
5 | import javafx.scene.Parent
6 | import javafx.scene.Scene
7 | import javafx.stage.Stage
8 |
9 | /**
10 | * Created by jt on 5/9/15.
11 | */
12 | class App extends Application{
13 |
14 | public static void main(String[] args) {
15 | launch(App.class, args)
16 | }
17 |
18 | @Override
19 | void start(Stage primaryStage) throws Exception {
20 | Parent root = FXMLLoader.load(getClass().getResource("/fxml/app.fxml"));
21 | primaryStage.setTitle "Android String XML-CSV parser"
22 | primaryStage.setScene(new Scene(root, 600, 400))
23 | primaryStage.show()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/javafx_gui/src/main/groovy/org/pandawarrior/Controller.groovy:
--------------------------------------------------------------------------------
1 | package org.pandawarrior
2 |
3 | import javafx.event.ActionEvent
4 | import javafx.scene.control.Label
5 | import javafx.scene.control.RadioButton
6 | import javafx.scene.control.TextField
7 | import javafx.scene.control.ToggleGroup
8 | import javafx.scene.paint.Color
9 | import javafx.stage.DirectoryChooser
10 | import javafx.stage.FileChooser
11 | import javafx.stage.Stage
12 | import org.pandawarrior.app.CSVToXMLKt
13 | import org.pandawarrior.app.TranslationType
14 | import org.pandawarrior.app.XMLToCSVKt
15 |
16 | /**
17 | * Created by jt on 5/10/15.
18 | */
19 | class Controller {
20 |
21 | public TextField x2c_txtXMLFolder
22 | public TextField x2c_txtCSVFile
23 | public TextField c2x_txtCSVFile
24 | public TextField c2x_txtXMLFolder
25 | public Label c2x_indicator
26 | public Label x2c_indicator
27 | public RadioButton c2x_strings_radio
28 | public ToggleGroup myToggleGroup
29 | public RadioButton c2x_plurals_radio
30 | public RadioButton c2x_arrays_radio
31 |
32 | /**
33 | * XML to CSV
34 | * @param actionEvent
35 | */
36 | public void x2c_openXMLFolder(ActionEvent actionEvent) {
37 | DirectoryChooser chooser = new DirectoryChooser();
38 | chooser.setTitle("Select folder");
39 | File folder = chooser.showDialog(new Stage());
40 | x2c_txtXMLFolder.setText folder.absolutePath
41 | }
42 |
43 | public void x2c_saveDestination(ActionEvent actionEvent) {
44 | DirectoryChooser chooser = new DirectoryChooser();
45 | chooser.setTitle("Select Save Folder");
46 | File file = chooser.showDialog(new Stage())
47 | x2c_txtCSVFile.setText "${file.absolutePath}"
48 |
49 | }
50 |
51 | void x2c_runXMLtoCSV(ActionEvent actionEvent) {
52 | try {
53 | String folderPath = x2c_txtXMLFolder.getText()
54 | String filePath = x2c_txtCSVFile.getText()
55 | if (folderPath.length() > 0 && filePath.length() > 0) {
56 | XMLToCSVKt.processXMLToCSV(folderPath, filePath, TranslationType.NORMAL)
57 | XMLToCSVKt.processXMLToCSV(folderPath, filePath, TranslationType.PLURALS)
58 | XMLToCSVKt.processXMLToCSV(folderPath, filePath, TranslationType.ARRAYS)
59 | x2c_txtCSVFile.clear()
60 | x2c_txtXMLFolder.clear()
61 | x2c_indicator.setText("SUCCESS!")
62 | x2c_indicator.setTextFill(Color.GREEN)
63 | } else {
64 | x2c_indicator.setText("Please set folder or file location!")
65 | x2c_indicator.setTextFill(Color.RED)
66 | }
67 | } catch (Exception e) {
68 | if (e.message != null) {
69 | x2c_indicator.setText(e.message)
70 | } else {
71 | x2c_indicator.setText("Error! Try adding a space or null in the empty values")
72 | }
73 | x2c_indicator.setTextFill(Color.RED)
74 | }
75 |
76 | }
77 |
78 | public void c2x_openCSVFile(ActionEvent actionEvent) {
79 | FileChooser chooser = new FileChooser();
80 | chooser.setTitle("Open File")
81 | chooser.getExtensionFilters().add(
82 | new FileChooser.ExtensionFilter("CSV File (*.csv)", "*.csv")
83 | )
84 | File file = chooser.showOpenDialog(new Stage());
85 | c2x_txtCSVFile.setText "${file.absolutePath}"
86 | }
87 |
88 | public void c2x_saveDestination(ActionEvent actionEvent) {
89 | DirectoryChooser chooser = new DirectoryChooser();
90 | chooser.setTitle("Select folder");
91 | File folder = chooser.showDialog(new Stage());
92 | c2x_txtXMLFolder.setText folder.absolutePath
93 | }
94 |
95 | public void c2x_runCSVtoXML(ActionEvent actionEvent) {
96 | try {
97 | String selected = (myToggleGroup.selectedToggle as RadioButton).text
98 | String csvFilePath = c2x_txtCSVFile.getText()
99 | String xmlFolderPath = c2x_txtXMLFolder.getText()
100 |
101 | boolean result
102 | switch (selected) {
103 | case "arrays.xml":
104 | result = CSVToXMLKt.processCSVToXML(csvFilePath, xmlFolderPath, TranslationType.ARRAYS)
105 | break;
106 | case "plurals.xml":
107 | result = CSVToXMLKt.processCSVToXML(csvFilePath, xmlFolderPath, TranslationType.PLURALS)
108 | // result = WriteXml.parseArray(c2x_txtCSVFile.getText(), c2x_txtXMLFolder.getText(), WriteXml.PLURALS_FILE)
109 | break;
110 | default:
111 | result = CSVToXMLKt.processCSVToXML(csvFilePath, xmlFolderPath, TranslationType.NORMAL)
112 | //result = WriteXml.parse(c2x_txtCSVFile.getText(), c2x_txtXMLFolder.getText())
113 | }
114 |
115 | c2x_txtCSVFile.clear()
116 | c2x_indicator.setText("SUCCESS!")
117 | c2x_indicator.setTextFill(Color.GREEN)
118 |
119 | } catch (Exception e) {
120 | if (e.message != null && e.message.length() > 0) {
121 | c2x_indicator.setText(e.message)
122 | } else {
123 | c2x_indicator.setText("Error! Try adding a space or null in the empty values")
124 | }
125 | c2x_indicator.setTextFill(Color.RED)
126 | }
127 |
128 | }
129 |
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/javafx_gui/src/main/resources/fxml/app.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This settings file was auto generated by the Gradle buildInit task
3 | * by 'jt' at '5/9/15 2:07 PM' with Gradle 2.4
4 | *
5 | * The settings file is used to specify which projects to include in your build.
6 | * In a single project build this file can be empty or even removed.
7 | *
8 | * Detailed information about configuring a multi-project build in Gradle can be found
9 | * in the user guide at http://gradle.org/docs/2.4/userguide/multi_project_builds.html
10 | */
11 |
12 | /*
13 | // To declare projects as part of a multi-project build use the 'include' method
14 | include 'shared'
15 | include 'api'
16 | include 'services:webservice'
17 | */
18 |
19 | rootProject.name = 'groovy-app'
20 | include 'javafx_gui', 'Kotlin-XML-CSV-Parser', 'ide-plugin'
21 |
--------------------------------------------------------------------------------
/strings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiewJunTung/Android-strings-xml-csv-converter/554369bdceb28869043e8e8bef2522b61fd1ffbf/strings.png
--------------------------------------------------------------------------------
/xml_csv_parse/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This build file was auto generated by running the Gradle 'init' task
3 | * by 'jt' at '5/9/15 2:07 PM' with Gradle 2.4
4 | *
5 | * This generated file contains a commented-out sample Java project to get you started.
6 | * For more details take a look at the Java Quickstart chapter in the Gradle
7 | * user guide available at http://gradle.org/docs/2.4/userguide/tutorial_java_projects.html
8 | */
9 |
10 | // In this section you declare the dependencies for your production and test code
11 | dependencies {
12 | compile 'org.slf4j:slf4j-api:1.7.12'
13 | compile 'org.codehaus.groovy:groovy-all:2.4.3'
14 | testCompile 'junit:junit:4.12'
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/xml_csv_parse/src/main/groovy/org/pandawarrior/ReadXml.groovy:
--------------------------------------------------------------------------------
1 | package org.pandawarrior
2 |
3 | import java.util.regex.Pattern
4 |
5 | /**
6 | * Created by jt on 5/9/15.
7 | */
8 | class ReadXml {
9 |
10 | final static String STRING_ARRAY = "string-array"
11 | final static String PLURALS = "plurals"
12 | final static String STRINGS = "strings"
13 | final static Pattern PLURALS_PATTERN = ~/plurals.xml/
14 | final static Pattern STRINGS_PATTERN = ~/strings.xml/
15 | final static Pattern ARRAYS_PATTERN = ~/arrays.xml/
16 |
17 | /**
18 | * Parse all the strings.xml, plurals.xml, arrays.xml to their respective csv
19 | * @param moduleFolder
20 | * @param csvDestination
21 | * @return boolean
22 | */
23 | static boolean parseAll(String moduleFolder, String csvDestination){
24 | parse(moduleFolder, csvDestination, STRINGS)
25 | boolean arrayFlag = parseArray(moduleFolder, csvDestination, STRINGS_PATTERN, STRING_ARRAY)
26 | boolean pluralFlag = parseArray(moduleFolder, csvDestination, STRINGS_PATTERN, PLURALS)
27 | if (!arrayFlag){
28 | parseArray(moduleFolder, csvDestination, ARRAYS_PATTERN, STRING_ARRAY)
29 | }
30 | if (!pluralFlag){
31 | parseArray(moduleFolder, csvDestination, PLURALS_PATTERN, PLURALS)
32 | }
33 | return true
34 | }
35 |
36 | /**
37 | *
38 | * @param moduleFolder folder path
39 | * @param csvDestination csv folder path
40 | * @param pattern
41 | * @param type
42 | * @return
43 | */
44 | static boolean parseArray(String moduleFolder, String csvDestination, Pattern pattern, String type) {
45 | Map stringsXMLMap = getXmlFromFolder(moduleFolder, pattern)
46 | if (stringsXMLMap.size() > 0){
47 | Map arrayMap = getArrayMap(stringsXMLMap, type)
48 | Map translatableMap = getTranslatableArray(stringsXMLMap, type)
49 | List nameList = getArrayNameList(stringsXMLMap, type)
50 | List valueList = getArrayValueList(arrayMap, nameList, translatableMap)
51 | List headerList = getHeaderList(arrayMap);
52 | String csv = createCSV(headerList, valueList)
53 | new File("${csvDestination}/${type}.csv").withWriter('utf-8') { writer ->
54 | writer.write(csv)
55 | }
56 | return true
57 | } else {
58 | return false
59 | }
60 | }
61 |
62 | static boolean parse(String moduleFolder, String csvDestination, String type) {
63 |
64 | //scan the Android module recursively for strings.xml
65 | Map stringsXMLMap = getXmlFromFolder(moduleFolder, ~/strings.xml/)
66 | if (stringsXMLMap != null){
67 | //create a map with all the necessary stuff
68 | Map mainMap = getMainMap(stringsXMLMap)
69 | //get a map of all translatables
70 | Map translatableMap = getTranslatable(stringsXMLMap)
71 | //create a map for the default names
72 | List nameList = getNameList(stringsXMLMap)
73 | //reorder the data into list
74 | List valueList = getValueList(mainMap, nameList, translatableMap)
75 | List headerList = getHeaderList(mainMap)
76 | String csv = createCSV(headerList, valueList)
77 | // println(csv)
78 | new File("${csvDestination}/${type}.csv").withWriter('utf-8') { writer ->
79 | writer.write(csv)
80 | }
81 | return true
82 | }else{
83 | return false
84 | }
85 | }
86 |
87 | protected static Map getXmlFromFolder(String dirname, Pattern pattern) {
88 | Map stringsXMLMap = [:]
89 | try{
90 | new File(dirname).eachDirRecurse { dir ->
91 | dir.eachFileMatch(pattern) { myfile ->
92 | String xmlString = new File(myfile.path).getText()
93 | stringsXMLMap[myfile.getParentFile().getName()] = xmlString
94 | }
95 | }
96 | return stringsXMLMap;
97 | }catch (FileNotFoundException e){
98 | return null;
99 | }
100 | }
101 |
102 | protected static List getHeaderList(Map mainMap) {
103 | List headerList = ["name", "translatable"]
104 | headerList.addAll mainMap.keySet()
105 | return headerList
106 | }
107 |
108 | protected static List getValueList(Map mainMap, List nameList, Map translatableMap) {
109 | List valueList = []
110 | nameList.each { it ->
111 | String tempName = it
112 | List tempList = []
113 | tempList.add tempName
114 | tempList.add translatableMap[tempName]
115 | mainMap.each {
116 | def tempMainMap = it.value
117 | tempList.add tempMainMap[tempName]
118 | }
119 | valueList.add tempList
120 | }
121 | return valueList
122 | }
123 |
124 |
125 | protected static List getArrayValueList(Map arrayMap, List nameList, Map translatableMap) {
126 | List valueList = []
127 | nameList.each { String name ->
128 | def tempArray = arrayMap["values"][name].collect()
129 | def tempSize = tempArray.size()
130 | for (int i = 0; i < tempSize; i++) {
131 | List tempList = []
132 | tempList.add name
133 | tempList.add translatableMap[name]
134 | arrayMap.each { map ->
135 | def tempMainMap = map.value
136 | def fooList = tempMainMap[name].collect()
137 | tempList.add fooList[i]
138 | }
139 | valueList.add tempList
140 | }
141 | }
142 | return valueList
143 | }
144 |
145 | protected static List getNameList(Map stringsXMLMap) {
146 | List nameList = []
147 | String mainValues = stringsXMLMap["values"]
148 | def xml = new XmlSlurper().parseText mainValues
149 | xml.string.each {
150 | nameList.add(it.@name as String)
151 | }
152 | return nameList
153 | }
154 |
155 | protected static List getArrayNameList(Map stringsXMLMap, String type) {
156 | List nameList = []
157 | String mainValues = stringsXMLMap["values"]
158 | def xml = new XmlSlurper().parseText mainValues
159 | xml[type].each {
160 | nameList.add(it.@name as String)
161 | }
162 | return nameList
163 | }
164 |
165 | protected static Map getMainMap(Map stringsXMLMap) {
166 | Map mainMap = [:]
167 | stringsXMLMap.each {
168 | def tempMap = [:]
169 | String xmlFile = it.value
170 | def tempXml = new XmlSlurper().parseText(xmlFile)
171 | def tempResources = tempXml.string
172 | tempResources.each {
173 | tempMap[it.@name as String] = it.text()
174 | }
175 | mainMap[it.key] = tempMap
176 | // println mainMap
177 | }
178 | return mainMap
179 | }
180 |
181 | protected static Map getArrayMap(Map stringsXMLMap, String type) {
182 | Map mainMap = [:]
183 | stringsXMLMap.each {
184 | def tempMap = [:]
185 | String xmlFile = it.value
186 | def tempXml = new XmlSlurper().parseText(xmlFile)
187 | def tempResources = tempXml[type]
188 | tempResources.each { arrayName ->
189 | tempMap[arrayName.@name as String] = arrayName.item.collect { it }
190 | }
191 | mainMap[it.key] = tempMap
192 | // println mainMap
193 | }
194 | return mainMap
195 | }
196 |
197 | protected static Map getTranslatableArray(Map stringsXMLMap, String type) {
198 | Map resultMap = [:]
199 | String xml = stringsXMLMap["values"]
200 | // println xml
201 | def tempXml = new XmlSlurper().parseText(xml)
202 | // println tempXml
203 | def tempResources = tempXml[type]
204 | tempResources.each {
205 | resultMap[it.@name as String] = it.@translatable.equals("false") ? it.@translatable : "true"
206 | }
207 | return resultMap
208 | }
209 |
210 | protected static Map getTranslatable(Map stringsXMLMap) {
211 | Map resultMap = [:]
212 | String xml = stringsXMLMap["values"]
213 | // println xml
214 | def tempXml = new XmlSlurper().parseText(xml)
215 | def tempResources = tempXml.string
216 | tempResources.each {
217 | resultMap[it.@name as String] = it.@translatable.equals("false") ? it.@translatable : "true"
218 | }
219 | return resultMap
220 | }
221 |
222 | protected static String createCSV(List headerList, List valueList) {
223 | String csv
224 | csv = '\"'+headerList.join('\",\"') + '\"\n'
225 | valueList.each {
226 | csv += it.collect({it!=null?"\"${it}\"":'\"\"'}).join(',')
227 | csv += '\n'
228 | }
229 | return csv
230 | }
231 | }
--------------------------------------------------------------------------------
/xml_csv_parse/src/main/groovy/org/pandawarrior/WriteXml.groovy:
--------------------------------------------------------------------------------
1 | package org.pandawarrior
2 |
3 | import groovy.xml.MarkupBuilder
4 |
5 | /**
6 | * Created by jt on 5/9/15.
7 | */
8 | class WriteXml {
9 |
10 | final static String ARRAY_FILE = "arrays"
11 | final static String PLURALS_FILE = "plurals"
12 | private static final String REGEX = /,(?=([^\"]*\"[^\"]*\")*[^\"]*$)/
13 |
14 | static boolean parse(String csvPath, String moduleFolder) {
15 | //load and split the file
16 | List rows = getRows(csvPath)
17 | List head = getHead(rows)
18 | Map mainDict = getMainMap(rows, head)
19 | Map transDict = getTransMap(rows)
20 | return writeFile(moduleFolder, mainDict, transDict)
21 | }
22 |
23 | static boolean parseArray(String csvPath, String moduleFolder, String type) {
24 | //load and split the file
25 | List rows = getRows(csvPath)
26 | List head = getHead(rows)
27 | Map transDict = getTransMap(rows)
28 | List nameList = getArrayNameList(transDict)
29 | Map mainDict = getMainArrayMap(rows, head, nameList)
30 | return writeArrayFile(moduleFolder, mainDict, transDict, type)
31 | }
32 |
33 | protected static List getRows(String csvPath) {
34 | String csv = new File(csvPath).getText()
35 | String[] lines = csv.split('\n')
36 | List rows = lines.collect{
37 | it.split(REGEX, -1)
38 | }
39 | return rows
40 | }
41 |
42 | protected static List getHead(List rows) {
43 | List head = rows.get(0)
44 | head = head - "\"name\""
45 | head = head - "name"
46 | head = head - "\"translatable\""
47 | head = head - "translatable"
48 | // println head
49 | return head
50 | }
51 |
52 | protected static Map getTransMap(List rows) {
53 | Map transMap = [:]
54 | for (int i = 1; i < rows.size(); i++) {
55 | transMap[rows[i][0]] = rows[i][1].replaceAll("\"", "")
56 | }
57 | return transMap
58 | }
59 |
60 | protected static Map getMainMap(List rows, List head) throws ArrayIndexOutOfBoundsException {
61 |
62 | Map mainDict = [:]
63 | // println rows
64 | for (int i = 0; i < head.size(); i++) {
65 | def tempMap = [:]
66 | for (int j = 1; j < rows.size(); j++) {
67 | def column = rows.get(j)
68 | def name = column[0]
69 | tempMap[name] = column[i + 2]
70 | }
71 | mainDict[head[i].replaceAll("\"", "")] = tempMap
72 | }
73 | return mainDict
74 | }
75 |
76 | protected static List getArrayNameList(Map transMap) {
77 | return transMap.collect { it.key }
78 | }
79 |
80 | protected static Map getMainArrayMap(List rows, List head, List nameList) {
81 | Map mainArrayMap = [:]
82 |
83 | for (int i = 0; i < head.size(); i++) {
84 | def tempMap = [:]
85 | nameList.each { String name ->
86 | def tempList = []
87 | for (int j = 1; j < rows.size(); j++) {
88 | def column = rows.get(j)
89 | def tempName = column[0]
90 | if (tempName == name) {
91 | tempList.add column[i + 2]
92 | tempMap[name] = tempList
93 | }
94 |
95 | }
96 | }
97 | mainArrayMap[head[i].replaceAll("\"", "")] = tempMap
98 | }
99 | return mainArrayMap
100 | }
101 |
102 | private static boolean writeFile(String destination, Map mainDict, Map transDict) {
103 | mainDict.each {
104 | def stringWriter = new StringWriter()
105 | def xml = new MarkupBuilder(stringWriter)
106 | def mainDictValue = it.value
107 | def fileName = it.key
108 | String dir = "${destination}/res/${fileName}/"
109 | File file = new File(dir, 'strings.xml')
110 | File folder = new File(dir)
111 |
112 | if (!folder.exists()) {
113 | folder.mkdirs()
114 | }
115 | xml.resources {
116 | mainDictValue.each {
117 | def key = it.key
118 | def value = it.value.replaceAll("\"", "")
119 | if (fileName.equals("values") && transDict[key].equals("false") ||
120 | fileName.equals("values") && !transDict[key]) {
121 | string(name: key.replaceAll("\"", ""), translatable: transDict[key], value)
122 | } else if (transDict[key].equals("true") && !value.equals("null") && !value.equals("") ||
123 | transDict[key] && !value.equals("null") && !value.equals("")
124 | ) {
125 | string(name: key.replaceAll("\"", ""), value)
126 | }
127 | }
128 | }
129 | def records = stringWriter.toString()
130 | file.withWriter('utf-8') { writer ->
131 | writer.write(records)
132 | }
133 | return true
134 | }
135 | }
136 |
137 | private static boolean writeArrayFile(String destination, Map mainArrayMap, Map transDict, String type) {
138 | mainArrayMap.each {
139 | def stringWriter = new StringWriter()
140 | def xml = new MarkupBuilder(stringWriter)
141 | def mainDictValue = it.value
142 | def fileName = it.key
143 | def rowName
144 | String dir = "${destination}/res/${fileName}/"
145 | File file = new File(dir, "${type}.xml")
146 | File folder = new File(dir)
147 |
148 | if (!folder.exists()) {
149 | folder.mkdirs()
150 | }
151 | rowName = type == ARRAY_FILE ? "string-array" : type
152 |
153 | xml.resources {
154 | mainDictValue.each {
155 | def key = it.key
156 | def value = it.value.collect()
157 | if (fileName.equals("values") && transDict[key].equals("false") ||
158 | fileName.equals("values") && !transDict[key]) {
159 | "${rowName}"(name: key, translatable: transDict[key]) {
160 | value.each {
161 | item(it)
162 | }
163 | }
164 | } else if (transDict[key].equals("true") || transDict[key]) {
165 | "${rowName}"(name: key) {
166 | value.each {
167 | if (!it.equals("null") || !it.equals(" ") || !it.equals("") ) {
168 | item(it)
169 | }
170 | }
171 | }
172 | }
173 | }
174 | }
175 | def records = stringWriter.toString()
176 | file.withWriter('utf-8') { writer ->
177 | writer.write(records)
178 | }
179 | return true
180 | }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/xml_csv_parse/xml_csv_parse.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------