大專案中網頁多語系的維護方式

也許在許多專案上我們所說的Multi Language僅有繁體中文、簡體中文和英文,但在比較大型且跨國的專案上,可能會涉及更多的語言,例如:日文、俄文、德文、法文、西班牙文…等等,通常這些軟體內容的翻譯,需要經過更專業的單位來進行,也許這個單位不僅僅需要具備有這些國家的語言能力,也要具備有相當的軟體知識,才能配合當地民情翻譯出正確的文字,這部分往往需要專業的翻譯單位來進行。

而專業的翻譯單位通常並不具有軟體的製作能力,所以在軟體上要如何快速地進行協同作業,就變成一項非常重要的工作,而在許多專案上,我們會讓翻譯單位透過Excel來提供各國語系的翻譯文字,我們則透過軟體進行轉換,將其轉換至軟體能快速讀取的格式,講白一點就是將Excel檔案轉換成XML格式,並提供其他軟體進行讀取。

整體流程會如上圖所示,在拿到一個翻譯社提供所有語系的Excel資料後,我們會進行轉換,將文字轉換成多個XML檔案,並打包成一個ZIP檔讓轉換者進行下載。

今天我們主要來分享上圖藍色部分的處理程序,也就是那一隻轉換程式的結構和做法,我們將轉換程式設計成網頁版本,藉此提升易用性,而轉換程式操作Flow大致如下:

  1. 使用者上傳檔案(限制僅能上傳Excel檔案)
  2. 給出ZIP下載連結(提供使用者下載所有語系的XML檔)

操作上非常簡單,僅有上述這兩個步驟,而程式設計上採用JSP架構其運作邏輯如下:

  1. 檢查上傳檔案的格式、容量及相關資訊
  2. 擷取Excel中第一張工作表(也可以依照工作表名稱擷取)
  3. 將Excel中第一列視為語系標題,並當作存檔名稱(例如:English.xml)
  4. 將剩下來的每一列轉換為該檔案的語系資料,並建立XML檔案
  5. 將所有建立好的XML檔案進行打包(ZIP)
  6. 更新頁面產生ZIP檔下載路徑

在該轉換程式中,另外有利用到下述的JAVA Library:

  1. Apache POI – 處理與解析Excel檔案
  2. DOM4J – 建立XML檔案
  3. Apache Commons – 處理檔案上傳

以下是轉換的程式碼:

<%@ page contentType="text/html; charset=UTF-8"%>

<%@ page import="java.io.File"%>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.List"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.io.FilenameUtils"%>

<%@ page import="java.util.zip.ZipEntry"%>
<%@ page import="java.util.zip.ZipOutputStream"%>

<%@ page import="java.io.FileInputStream"%>
<%@ page import="java.io.FileOutputStream"%>
<%@ page import="java.io.IOException"%>
<%@ page import="java.io.OutputStreamWriter"%>
<%@ page import="java.nio.charset.Charset"%>

<%@ page import="org.apache.poi.hssf.usermodel.HSSFRow"%>
<%@ page import="org.apache.poi.hssf.usermodel.HSSFSheet"%>
<%@ page import="org.apache.poi.hssf.usermodel.HSSFWorkbook"%>

<%@ page import="org.dom4j.io.OutputFormat"%>
<%@ page import="org.dom4j.io.XMLWriter"%>
<%@ page import="org.dom4j.Document"%>
<%@ page import="org.dom4j.DocumentHelper"%>
<%@ page import="org.dom4j.Element"%>


<%!
    //允許上傳的檔案
  String allowedFileTypes = ".xls";
  
  //建立目錄
    public void newFolder(String folderPath) {
        try {
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            if (!myFilePath.exists()) {
                myFilePath.mkdir();
            }
        }
        catch(Exception e) {
            System.out.println("建立目錄錯誤");
            //e.printStackTrace();
        }
    }
   
   // 轉換XLS為XML的主程式 ; 參數1.欲轉換的Excel工作表編號; 參數2.轉換的檔案路徑與檔名; 參數3.XML儲存的檔案路徑;
   public static String convertSheet(int sheetNumber, String conversionFile, String conversionXMLFilePath) {
     
     String convertStatus = "0"; // 輸出轉換狀態 ; 0 是失敗; 1是成功
     String conversionXMLFileName = null; // XML檔名
     String conversionXMLFile = null; // XML完整路徑與檔名
     
     // 產生儲存XML檔案的資料夾
     File file = new File(conversionXMLFilePath);
     if(!file.exists()){
         file.mkdirs();
     }
     
     // 開始讀取XLS檔案
     HSSFWorkbook book = null;
     try {
       book = new HSSFWorkbook(new FileInputStream(conversionFile));
     } catch (IOException e) {
       System.out.println("IOException : " + e);
     }
     
     HSSFSheet sheet = book.getSheetAt(sheetNumber); // 打開對應編號的工作表
     HSSFRow row = sheet.getRow(0);// 取得工作表的第一列資料
     String cell;
     int totalRows = sheet.getPhysicalNumberOfRows(); // 取得工作表中所有的列數
     int totalCol = row.getPhysicalNumberOfCells(); // 取的工作表中所有的欄數
     
     // 開始建立XML檔並將XLS內容建入
     for (int j = 1; j < totalCol; j++){
       Document document = DocumentHelper.createDocument();
       Element root = document.addElement("root");
       
       for (int i = 0; i < totalRows; i++){
         row = sheet.getRow(i);
         try {
           cell = row.getCell(j).toString();
           if(i==0) {
             conversionXMLFileName = cell;
             conversionXMLFile = conversionXMLFilePath + conversionXMLFileName + ".xml";
           }else {
             root.addElement("row_" + (i+1)).addCDATA(cell);
             /*
             if(sheetNumber == 0) {
               root.addElement("tag_" + (i-1), cell);
             }else {
               root.addElement(xmlKeyboardTitle[(i-1)], cell);
             }
             */
           }
         } catch (NullPointerException e) {
           break;
         }
       }
       
       File storedFile = new File(conversionXMLFile);
       
       if(storedFile.exists())
         storedFile.delete();

       FileOutputStream fos = null;
       OutputStreamWriter osw = null;
       XMLWriter writer = null;
       try {
         storedFile.createNewFile();
         OutputFormat format = OutputFormat.createPrettyPrint();  
               format.setEncoding("utf-8");
               fos = new FileOutputStream(storedFile);
               osw = new OutputStreamWriter(fos, Charset.forName("utf-8"));
               writer = new XMLWriter(osw, format);
               writer.write(document);
       } catch (IOException e) {
         System.out.println("IOException : " + e);
       } finally {
         try {
           if(writer != null) writer.close();
           if(osw != null) osw.close();
           if(fos != null) fos.close();
           convertStatus = "1";
         } catch (IOException e) {
           System.out.println("IOException : " + e);
         }
       }
     }
     return convertStatus; // 回覆轉換狀態
   }
   
   List<String> filesListInDir = new ArrayList<String>();
   
   public void zipDirectory(File dir, String zipDirName) {
     
     filesListInDir = new ArrayList<String>();
     
        try {
          
            populateFilesList(dir);
            //now zip files one by one
            //create ZipOutputStream to write to the zip file
            FileOutputStream fos = new FileOutputStream(zipDirName);
            ZipOutputStream zos = new ZipOutputStream(fos);
            for(String filePath : filesListInDir){
                System.out.println("Zipping "+filePath);
                //for ZipEntry we need to keep only relative file path, so we used substring on absolute path
                ZipEntry ze = new ZipEntry(filePath.substring(dir.getAbsolutePath().length()+1, filePath.length()));
                zos.putNextEntry(ze);
                //read the file and write to ZipOutputStream
                FileInputStream fis = new FileInputStream(filePath);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
                fis.close();
            }
            zos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
   private void populateFilesList(File dir) throws IOException {
        File[] files = dir.listFiles();
        for(File file : files){
            if(file.isFile()) filesListInDir.add(file.getAbsolutePath());
            else populateFilesList(file);
        }
    }
  
%>

<%

String messageReturn = "";
  
try{
  
    request.setCharacterEncoding("utf-8");
    DiskFileUpload fileUpload = new DiskFileUpload();
  List<FileItem> fileItems = fileUpload.parseRequest(request);
  FileItem fileItem = fileItems.get(0);
  
    //原始上傳檔案名稱
  String originalFileName = fileItem.getName();
    //out.print("originalFileName : " + originalFileName + "<br>");
    
  if (originalFileName != null && !"".equals(originalFileName)) {

        originalFileName = FilenameUtils.getName(originalFileName);
        String extension = FilenameUtils.getExtension(originalFileName);
        
    //判斷檔案格式是否允許
    //out.print("extension : " + extension + "<br>");
        if (allowedFileTypes.indexOf(extension.toLowerCase()) != -1) {
            String filePath = this.getServletContext().getRealPath(request.getRequestURI().substring(request.getContextPath().length()));
            String savePath = new File(filePath).getParent() + "/upload";
          //out.println("savePath = " + savePath + "<br>");
      newFolder(savePath);
      
          String savePathAndName = savePath + "/" + originalFileName;
            //out.print(savePathAndName);
      
          File f = new File(savePathAndName);
          if(!f.exists()){
            f.createNewFile();
          }
          fileItem.write(f);
            
            //messageReturn += "File path : " + savePath + "<br>";
            
             String xmlSavePath = savePath + "/xml/";
             //messageReturn += "xmlSavePath : " + xmlSavePath + "<br>";
            
            if("1".equals(convertSheet(0, savePathAndName , xmlSavePath))){
              messageReturn += "File converted successfully.<br>";
        }else{
          messageReturn += "File conversion failed.<br>";
        };
        
        /*
        xmlSavePath = savePath + "/xml/keyboard/";
        
        if("1".equals(convertSheet(1, savePathAndName , xmlSavePath))){
              messageReturn += "Keyboard sheet conversion succeeded.<br>";
        }else{
          messageReturn += "Keyboard sheet conversion fail.<br>";
        };
        */
      
        java.io.File myDelFile = new java.io.File(savePath + "/All.zip");
        myDelFile.delete();
        
        zipDirectory(new File(savePath + "/xml/"), savePath + "/All.zip");
        
        messageReturn += "<a href='upload/All.zip' target='_blank'>Download Link</a><br>";

        } else {
          messageReturn += "上傳錯誤 : 上傳的檔案不能是" + extension + ",僅允許xls格式<br>";
        }
    }
}catch(Exception e){
  //e.printStackTrace();
}

%>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>AIOT CC Multi-Language Convertion Tool</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <style>
        *{
            font-family: 微軟正黑體;
        }
        h2{
            text-align: center;
        }
        .marginBottom20{
            margin-bottom: 20px;
        }
        #uploadBtn{
            margin: auto;
            display: block;
        }
        #messageDiv{
          color: red;
          text-align:center;
        }
    </style>
</head>

<body>

    <div class="container">
        <h2 class="marginBottom20">AIOT CC Multi-Language Convertion Tool</h2>
        <div class="form-group text-center">
          <form name="upload" enctype="multipart/form-data" method="post" action="index.jsp" onsubmit="return check_select()">
            <input type="file" name="file" id="file" size="60" maxlength="20" placeholder="*.xls" class="marginBottom20">
            <input id="uploadBtn" type="submit" value="轉換" class="btn btn-primary">
        </form>
      </div>
      <div id="messageDiv"><% out.print(messageReturn); %></div>
    </div>
    
</body>

</html>
<script>
    function check_select(form) {
        if (file.value == "") {
            alert("請選擇檔案");
            return false;
        } else {
            // document.getElementById("uploadBtn").disabled = true;
            //document.getElementById("msgDiv").innerHTML = "檔案上傳中,請稍候";
            return true;
        }
    }
</script>

You may also like...

94,118 Responses

  1. Edwardopele表示:

    comprare farmaci online con ricetta: Farma Prodotti – Farmacie online sicure

  2. BradleyThine表示:

    comprare farmaci online con ricetta: Farma Prodotti – farmacie online sicure
    п»їFarmacia online migliore

  3. промокод продамус скидка на подключение https://promokod-pro.ru .

  4. Clinterete表示:

    https://farmatadalitaly.com/# Farmacie on line spedizione gratuita
    farmacia online

  5. new porn表示:

    Cómo aumentar el área de la tienda en su hogar \”Animal Crossing: New Horizons\”

  6. MichaelUsaws表示:

    https://farmatadalitaly.com/# farmacie online autorizzate elenco
    comprare farmaci online con ricetta

  7. NathanSal表示:

    top farmacia online Cialis generico prezzo Farmacie online sicure

  8. BradleyThine表示:

    viagra originale in 24 ore contrassegno: Viagra – viagra generico sandoz
    farmacie online affidabili

  9. промокод продамус http://www.promokod-pro.ru/ .

  10. Начни на Фактические Средства с Комфортом! Онлайн покер – это ни просто игра, данное вся вселенная волнения, стратегии и возможности заработать реальные деньги, не выходя из дома. Если вы ищете где поиграть на покер в интернете, на русском языке а с выводом денег прямо на карту, то ты оказались нужному месту. Данная статья – ваш гид в мир онлайн покера в россии.

    Почему Онлайн Покер так Известен? Покер – это классическая карточная игра, которая веками завлекала миллионы людей. Онлайн формат принес этой новую жизнь, сделав игры доступными для всех жаждущих. Здесь только несколько оснований популярности онлайн покера:

    Удобство а открытость: Играть можно в любое время и в любом месте, имея только доступ к браузере или мобильному устройству. Большой выбор: Покеррумы дают различные виды покера, варианты турниров а уровни ставок. Играть с реальными людьми: Ты способен бороться с реальными соперниками со всего мира, а ни с компьютерными ботами. Шанс выигрывать реальные деньги: Играть на деньги – это не просто волнение, но и шанс пополнить свой бумажник. Социальный аспект: Возможно играть с друзьями или заводить свежие знакомства с людьми, разделяющих ваш интерес. Где Играть в Онлайн Покер в россии на Реальные Деньги? В россии существует множество сайты и покеррумы, предлагающих игры в онлайн покер. Однако как подобрать лучший среди них? Мы поможем вам разобраться:

    Популярные Покеррумы для Русских Игроков:

    Мы составили рейтинг лучших покеррумов для русском языке игроков, беря во внимание такие критерии:

    Наличие русского языка: Интерфейс а поддержка должны быть на русском языке. Возможность играть на рубли: Депозиты а вывод средств обязаны быть доступны в рублях. Многообразие игр и турниров: Широкий выбор столов и турниров для всевозможных уровней игроков. Наличие мобильного приложения: Возможность скачать приложение для андроид и играть с мобильного устройства. Наличие прибыльных бонусов: Бездепозитным бонусом за регистрацию, начальным капиталом, бонусы на депозит а другие акции. Безопасность а репутация: Безопасность транзакций и честность игры. Топ румов регулярно обновляется, поэтому рекомендуем следить за свежими обзорами и отзывами игроков.

    Особое Внимание на Минимальный Депозит:

    Если вы новичок, то следует обратить внимание на покеррумы с минимальным депозитом. Данное позволит вам начать играть на реальные деньги без крупных финансовых вложений.

    Разрешенные Покеррумы:

    Проверьте, что выбранный вами рум есть разрешенным в россии, чтобы избежать возможных проблем с доступом и выводом средств.

    Онлайн Покер с Выводом Денег на Карту: Как Это Работает? После того, как ты решили с покеррумом а подобрали игру, ты можете положить твой баланс и начать играть на деньги. Большая часть сайтов предлагают различные способы пополнения и вывода средств, в том числе:

    Банковские карты (Visa, Mastercard) Электронные кошельки Другие платежные системы Вывод денег на карту как правило занимает от нескольких часов до нескольких дней, в зависимости от рума и подобранного способа вывода.

    Как Играть в Онлайн Покер с Друзьями? Многие покеррумы предлагают возможность играть с друзьями за приватными столами. Это отличный способ уделить время с людьми, с которыми вы знакомы, и сразиться за звание лучшего игрока в твоей компании.

    Бесплатный Покер: Возможность Попробовать Свои Силы Если ты новичок и хотите вначале привыкнуть с правилами, многие сайты предлагают шанс играть в бесплатный покер. Данное прекрасный метод потренироваться а получить опыта перед тем, как начать играть на реальные деньги.

    Покер на пк: Комфорт и Удобство Когда вы предпочитаете играть на пк, тогда большая часть покеррумов предлагают программы для компьютеров, которые обеспечивают более комфортный а надежный игровой процесс.

    Заключение: Начните Свой Путь в Мир Онлайн Покера Сегодня! Онлайн покер – есть захватывающая игра, что способна предоставить тебе ни только удовольствие, а и реальные деньги. Выбирайте надежные сайты и румы, принимайте участие в турнирах, играйте с друзьями и людьми со всего мира, и знайте, что главное – это испытывать удовольствие от игры!

    Ни откладывайте на потом, начните свою игру в онлайн покер непосредственно сейчас! Погрузитесь в мир тактики, азарта и шансов! Удачи за столами!

  11. Clinterete表示:

    https://farmasilditaly.shop/# siti sicuri per comprare viagra online
    Farmacia online piГ№ conveniente

  12. Edwardopele表示:

    Farmacia online piГ№ conveniente: comprare farmaci online con ricetta – Farmacie on line spedizione gratuita

  13. So, keep up the nice work and one day it is going to repay!

  14. Edwardopele表示:

    migliori farmacie online 2024: Brufen senza ricetta – migliori farmacie online 2024

  15. clindamycin for dogs warnings for clindamycin clindamycin phosphate topicalclindamycin side effects clindamycin classification clindamycin lotion

  16. BradleyThine表示:

    farmacie online affidabili: Cialis generico prezzo – farmacia online senza ricetta
    farmacia online

  17. NathanSal表示:

    farmaci senza ricetta elenco acquisto farmaci con ricetta migliori farmacie online 2024

  18. MichaelUsaws表示:

    https://farmaprodotti.com/# acquisto farmaci con ricetta
    Farmacia online miglior prezzo

  19. Architectural model created by intelligent and experienced modelers allow verifying the financial feasibility of the design.

  20. LarryLog表示:

    buy rybelsus online: cheap semaglutide pills – buy rybelsus online

  21. Waltererync表示:

    Kamagra 100mg price: Kama Pharm – super kamagra

  22. LarryLog表示:

    Misoprostol 200 mg buy online: buy cytotec online – buy cytotec online

  23. JesseWeide表示:

    mega sb вход – мега ссылки, mega.fo

  24. せんもく表示:

    There are quite a few pre-marriage ceremony rituals, marriage ceremony rituals, and post-marriage ceremony rituals to observe in Bihari weddings.

  25. JesseWeide表示:

    mega вход зеркало – megaweb12.at, актуальные зеркала мега

  26. JesseWeide表示:

    mega.fo – m3ga, mega.fo

  27. What Is The Best Way To Spot The Mesothelioma From Asbestos That Is Right For You Mesothelioma Lawsuit

  28. JesseWeide表示:

    m3ga – сайт мега, mega fo

  29. DanielZek表示:

    https://dappharm.com/# buy priligy
    Kamagra 100mg price

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。