I've been a Java developer for 11 years and using Netbean for 4 years. Currently I'm working in a game engine SDK named JMonkeyEngine http://jmonkeyengine.com Micheal has posted 1 posts at DZone. You can read more from them at their website. View Full User Profile

Why & How I Translated NetBeans into Vietnamese

03.06.2012
| 26105 views |
  • submit to reddit

My name is Cuong Nguyen Manh, in English Micheal Nguyen. I'm 25 years old. I have about 4 years experience working with NetBeans IDE and the NetBeans Platform. In my free time, I play games and that's why I also contribute to the jMonkeyEngine SDK which, just like NetBeans IDE, is based on the NetBeans Platform.

I work in the Solution Center of the Hipt Coporation, a company in Vietnam that mainly provides Data Warehouse Services and Solutions. Hipt is a partner of Oracle in Vietnam.

Background

I translated NetBeans to Vietnamese because there are a lot of developers in my company (and in Vietnam) working with NetBeans IDE. I don't really know the total number of developers in Vietnam using NetBeans IDE, but I do know that in most technical universities and companies, Vietnamese developers use NetBeans IDE to develop (as well as learn and teach) Java applications in the desktop, mobile, and web spheres. However, Vietnamese developers experience difficulties because they are typically not really good in English.

In fact, most of the world doesn’t speak English natively or doesn’t speak English very well. NetBeans IDE and the NetBeans Platform are becoming more and more popular and used in a lot of applications, from small to large scale. However, still, UI language is a big “barrier” preventing the world (imagine children and the elderly) learning programming and coming to NetBeans IDE. Asian countries have billions of people and about 15% speak English adequately. We now have official Chinese, Japanese and a few Asian languages supported by NetBeans IDE. It doesn't seem to be too hard to introduce a new programming language to NetBeans IDE, so why should it be difficult to introduce human languages?

At the same time, we at Hipt Corporation are researching aspects of the NetBeans Platform, and also digging deep into some of its open source subprojects too, to find what is good for our future applications. And, as I mentioned above, I'm also a contributor to another open source NetBeans Platform project, in the Game area, a game engine in Java, powered by OpenGL, which is jMonkeyEngine. The SDK of jMonkeyEngine (http://jmonkeyengine.com/sdk/) is based on the NetBeans Platform. We're looking at making it possible to create applications in the area of Games and Education, as well as Teaching Programs for Kids, of course, in whatever human language we choose.

However, in short, the main reason for me to translate NetBeans IDE is so that it will become more and more friendly with the Vietnamese user in mind, so that it can provide what they need and also what they want!

Screenshots

Here are some screenshots of the translated applications, NetBeans IDE and jMonkeyEngine SDK. I only spent 4 days, translating about 10000 segments in 4 main packages with the help of Machine Translate. You'll see that some English word remain untranslated, which is because some words cannot be translated into Vietnamese without losing their meaning. For example, "File" in English is also "File" in Vietnamese.

In the first screenshot, you can see the focus is on a translated menu:

And here the focus is on a translated menu in the jMonkeyEngine SDK:

Finally, here you see the focus on the welcome page and a login form in NetBeans IDE:

Translation Process

This is the process I followed, it works with NetBeans IDE 7.0 as well as with NetBeans IDE 7.1.

  1. Download things.

    http://dlc.sun.com.edgesuite.net/netbeans/7.0/final/zip/ide-l10n-201104080000.zip
    http://dlc.sun.com.edgesuite.net/netbeans/7.0/final/zip/netbeans-7.0-201104080000-src.zip
    http://www.omegat.org/en/downloads.html
  2. Read introductions.

    http://nblocalization.netbeans.org/index-l10n.html
    http://nblocalization.netbeans.org/docs/HOWTOs/How-to-translate-NetBeans-using-OmegaT.html
  3. Set up the OmegaT project.

        - Unzip ide-l10n-201104080000.zip.

        - Copy all the folders to Project1\source.

        - Set the Translated File Folder to locale-target.


  4. Do the translations.
  5. Build the project. In NetBeans IDE, make a free-form project and point to the OmegaT project path. Add the package "anttask", then add "MyTask.java" in the project.

Below, I determine what the JAR file name should be by reading the folder's path. This is why we call it a hack, but the only way you can know the cluster name is to build the whole NetBeans sources, which we don’t want to.

package anttask;

import java.io.File;
import java.util.HashMap;
import java.util.regex.Pattern;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class MyTask extends Task {

    String filename = "";
    String filepath = "";

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public void setFilepath(String filepath) {
        this.filepath = filepath;
    }

    HashMap<String, String> map = new HashMap<String, String>();

    public void execute() {

    // NOTE: I determine what the JAR filename should be
// by reading its folder path,
// this is why we call it a hack,
// but the only way you can know the cluster name
// is to build the whole source
// which we don’t want to do

        String[] split = filename.split(Pattern.quote("\\"));
        if (split.length < 2) {
            throw new BuildException("Incorrect path.");
        }

        String innerPath = filename;
        String parentPack = "";
        String parentPath = split[1];
        String jarName = split[2];

        log("\nsplit: " + split.length + "\nparentPath: " + parentPath);
   
        if (parentPath.equals("java")) {
            if (jarName.startsWith("org-")) {
               
            } else if (jarName.startsWith("projectui")){
                jarName.replace("projectui", "project-ui");
                parentPack = "org-netbeans-modules-";
            } else {
                parentPack = "org-netbeans-modules-";
            }
        } else if (parentPath.equals("ide")) {
            if (jarName.startsWith("org-")) {
               
            } else if (jarName.startsWith("projectui")){
                jarName.replace("projectui", "project-ui");
                parentPack = "org-netbeans-modules-";
            } else {
                parentPack = "org-netbeans-modules-";
            }
        } else if (parentPath.equals("platform")) {
            if (jarName.startsWith("org-")) {
            } else if (jarName.startsWith("projectui")){
                jarName.replace("projectui", "project-ui");
                parentPack = "org-netbeans-modules-";
            } else {
                parentPack = "org-netbeans-modules-";
            }
        } else if (parentPath.equals("nb")) {
            if (jarName.startsWith("org-")) {
               
            } else if (jarName.startsWith("projectui")){
                jarName.replace("projectui", "project-ui");
                parentPack = "org-netbeans-modules-";
            } else {
                parentPack = "org-netbeans-modules-";
            }
        }
        log("\nsplit: " + split.length + "\nparentPack: " + parentPack);

        jarName = parentPack + jarName;

        //getProject().setProperty("innerPath", innerPath);
        getProject().setProperty("jarName", jarName);

        log("Filename: " + filename + "\n path : " + filepath);
        log("\nJarname: " + jarName);

    }

}

Add a build.XML to your project:
<?xml version="1.0" encoding="UTF-8"?>

<project name="vi_locale_nbbuild" default="jar-up" basedir=".">
   
    <target name="init">
        <property name="locale.lang" value="vi"/>
        <property name="locale.dist" value="./dist"/>
        <property name="locale.src" value="./locale-target/src-todo"/>
        <property name="src.dir" value="java"/>
        <property name="classes.dir" value="classes"/>
        <property name="ant.libs.dir" value="F:\\DEV\\Project Structure and Complier\\apache-ant-1.8.2-bin\\apache-ant-1.8.2\\lib\\"/>
        <property name="jme.dir" value="F:\\jmonkeyplatform\\platform\\modules\\locale"/>
        <property name="antcontrib.lib" value="F:\\JGE\\Jar Tools\\ant-contrib-1.0b3-bin\\ant-contrib\\ant-contrib-1.0b3.jar"/>       
    </target>
   
    <target name="clean-ant-task" description="Delete all generated files" depends="init">
        <delete dir="${classes.dir}" failonerror="false"/>
        <delete file="${ant.project.name}.jar"/>
    </target>

    <path id="my.classpath">
        <fileset dir="${ant.libs.dir}">
            <include name="**/*.jar" />
        </fileset>
    </path>
   
    <target name="compile-ant-task" description="Compiles the Task" depends="init">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="true">
            <classpath path="my.classpath"/>
        </javac>
    </target>

    <target name="jar-ant-task" description="JARs the Task" depends="compile-ant-task">
        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
    </target>
      
    <target name="test-my-task" description="Use the Task" depends="jar-ant-task">
        <makepath/>
    </target>
   
    <taskdef resource="net/sf/antcontrib/antlib.xml">
        <classpath>
            <pathelement location="${antcontrib.lib}"/>
        </classpath>
    </taskdef>

    <taskdef name="makepath" classname="anttask.MyTask" classpath="${ant.project.name}.jar"/>
   
    <target name="jar-locale" depends="compile-ant-task,jar-ant-task">
        <delete dir="${locale.dist}"/>
        <echo>${locale.src}</echo>       
       
        <!-- UNICODE CONVERT -->
       
        <native2ascii src="${locale.src}" dest="${locale.src}" includes="**/*.properties" ext=".encode"/>
       
        <for param="filepath">
            <path>
                <dirset dir="${locale.src}" includes="**/*.properties"/>
            </path>
            <sequential>       
                <move file="@{filepath}" tofile="@{filepath}.saved" overwrite="true"/>
                <move file="@{filepath}.encode" tofile="@{filepath}" overwrite="true"/>
            </sequential>
        </for>
       
        <!-- END CONVERT -->

        <for param="filepath">

            <path>
                <dirset dir="${locale.src}" includes="*/*/*"/>
            </path>

            <sequential>

      <!-- do something -->
     
                <pathconvert property="filename">
                    <path location="@{filepath}"/>
                    <map from="${basedir}/locale-target/src-todo" to="" />
                </pathconvert>

                <makepath filename="${filename}" filepath="@{filepath}"/>

                <!-- JAR -->

                <jar destfile="${locale.dist}/${jarName}_${locale.lang}.jar" basedir="@{filepath}"/>

                <copy file="${locale.dist}/${jarName}_${locale.lang}.jar" tofile="${jme.dir}/${jarName}_${locale.lang}.jar" overwrite="true"/>
               
                <var name="filename" unset="true"/>

            </sequential>

        </for>      

    </target>

</project>

The properties have a clear meaning:

<property name="locale.lang" value="vi"/>
<property name="locale.dist" value="./dist"/>
<property name="locale.src" value="./locale-target/src-todo"/>
<property name="src.dir" value="java"/>
<property name="classes.dir" value="classes"/>
<property name="ant.libs.dir" value="F:\\DEV\\Project Structure and Complier\\apache-ant-1.8.2-bin\\apache-ant-1.8.2\\lib\\"/>
<property name="jme.dir" value="F:\\jmonkeyplatform\\platform\\modules\\locale"/>
<property name="antcontrib.lib" value="F:\\JGE\\Jar Tools\\ant-contrib-1.0b3-bin\\ant-contrib\\ant-contrib-1.0b3.jar"/>
  • locale.lang = “vi” // As Vietnamse or what your language short word
  • locale.src = “./locale-target/src-todo/” // Choose the dir you put all your folders
  • locale.dist = “WhereYourJarWillBePutInto”;
  • ant.libs.dir = “ThePathToAntLibs”; 
  • antcontrib.lib= “ThePathToAntContribLibs”; // We use FOR task

Conclusion

As for publication of the Vietnamse NetBeans IDE, I will make an open-source project for the plugin of the language package. Also, I will post my code in the Java forum for Vietnamese developers, namely http://congdongjava.com.

Published at DZone with permission of its author, Micheal Nguyen.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)