From 8e943b7104561c3b14cf223016698709c5ade4b5 Mon Sep 17 00:00:00 2001
From: lty <876263681@qq.com>
Date: 星期二, 03 二月 2026 15:37:26 +0800
Subject: [PATCH] #pda料箱组托和换码

---
 missing_en.txt                                                  |    0 
 found_keys.txt                                                  |    0 
 src/main/webapp/static/i18n/en/form.json                        |    5 
 src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java             |    1 
 scripts/mapping.json                                            |   37 ++
 src/main/webapp/static/i18n/en/table.json                       |   15 
 src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java  |    5 
 src/main/webapp/static/i18n/en/common.json                      |  483 ++++++++++++++++++++++++++++++
 scripts/update_i18n.ps1                                         |  146 +++++++++
 en_keys.txt                                                     |    0 
 src/main/webapp/static/i18n/en.json                             |    1 
 src/main/java/com/zy/asrs/controller/MobileController.java      |   34 ++
 src/main/resources/mapper/WrkDetlMapper.xml                     |    6 
 src/main/java/com/zy/asrs/entity/param/ReplaceBarcodeParam.java |   22 +
 cn_keys.txt                                                     |    0 
 src/main/webapp/static/i18n/en/date.json                        |   16 +
 src/main/webapp/static/i18n/en/layer.json                       |    5 
 missing_cn.txt                                                  |    0 
 scripts/add_missing_keys.ps1                                    |  101 ++++++
 scripts/find_missing_keys.ps1                                   |   28 +
 src/main/java/com/zy/asrs/service/WrkDetlService.java           |    1 
 21 files changed, 906 insertions(+), 0 deletions(-)

diff --git a/cn_keys.txt b/cn_keys.txt
new file mode 100644
index 0000000..7f09974
--- /dev/null
+++ b/cn_keys.txt
Binary files differ
diff --git a/en_keys.txt b/en_keys.txt
new file mode 100644
index 0000000..7f09974
--- /dev/null
+++ b/en_keys.txt
Binary files differ
diff --git a/found_keys.txt b/found_keys.txt
new file mode 100644
index 0000000..faaf20c
--- /dev/null
+++ b/found_keys.txt
Binary files differ
diff --git a/missing_cn.txt b/missing_cn.txt
new file mode 100644
index 0000000..faaf20c
--- /dev/null
+++ b/missing_cn.txt
Binary files differ
diff --git a/missing_en.txt b/missing_en.txt
new file mode 100644
index 0000000..faaf20c
--- /dev/null
+++ b/missing_en.txt
Binary files differ
diff --git a/scripts/add_missing_keys.ps1 b/scripts/add_missing_keys.ps1
new file mode 100644
index 0000000..ce4f9e1
--- /dev/null
+++ b/scripts/add_missing_keys.ps1
@@ -0,0 +1,101 @@
+$javaFiles = Get-ChildItem -Path "src/main/java" -Recurse -Filter "*.java"
+$foundKeys = @()
+foreach ($file in $javaFiles) {
+    $content = Get-Content $file.FullName
+    $matches = [regex]::Matches($content, 'response\.[a-zA-Z0-9_]+')
+    foreach ($match in $matches) {
+        $foundKeys += $match.Value
+    }
+}
+
+# Manually add keys mentioned by user or known to be missing from grep
+$manualKeys = @("response.mat_list", "response.menu_list", "response.mat_delete", "response.mat_update", "response.user_detail")
+$foundKeys += $manualKeys
+
+$foundKeys = $foundKeys | Sort-Object | Get-Unique
+
+# Exclude technical calls
+$exclude = @("response.getOutputStream", "response.setContentType", "response.setCharacterEncoding", "response.setHeader", "response.sendRedirect", "response.getWriter", "response.addCookie", "response.setStatus", "response.reset", "response.isSuccessful", "response.getStatus")
+$foundKeys = $foundKeys | Where-Object { $exclude -notcontains $_ }
+
+$enPath = "src/main/webapp/static/i18n/en.json"
+$cnPath = "src/main/webapp/static/i18n/zh-cn.json"
+$mapPath = "scripts/mapping.json"
+
+$enContent = Get-Content $enPath -Raw -Encoding UTF8
+$cnContent = Get-Content $cnPath -Raw -Encoding UTF8
+$mapContent = Get-Content $mapPath -Raw -Encoding UTF8 | ConvertFrom-Json
+
+# Parse existing keys
+$enKeys = [regex]::Matches($enContent, '"(response\.[^"]+)"') | ForEach-Object { $_.Groups[1].Value }
+$cnKeys = [regex]::Matches($cnContent, '"(response\.[^"]+)"') | ForEach-Object { $_.Groups[1].Value }
+
+$missingEn = $foundKeys | Where-Object { $enKeys -notcontains $_ }
+$missingCn = $foundKeys | Where-Object { $cnKeys -notcontains $_ }
+
+function Get-EnTrans($key) {
+    $parts = $key.Replace("response.", "").Split("_")
+    $text = $parts | ForEach-Object { $_.Substring(0,1).ToUpper() + $_.Substring(1) }
+    return $text -join " "
+}
+
+function Get-CnTrans($key) {
+    $keyRaw = $key.Replace("response.", "")
+    $parts = $keyRaw.Split("_")
+    $trans = ""
+    foreach ($part in $parts) {
+        $found = $false
+        if ($mapContent -ne $null) {
+            # Robust property check
+            if ($mapContent.PSObject.Properties.Name -contains $part) {
+                $trans += $mapContent.$part
+                $found = $true
+            }
+        }
+        
+        if (-not $found) {
+            if ($part.Length -gt 0) {
+                 $trans += $part.Substring(0,1).ToUpper() + $part.Substring(1)
+            }
+        }
+    }
+    return $trans
+}
+
+# Add to EN
+if ($missingEn.Count -gt 0) {
+    $newEntries = @()
+    foreach ($key in $missingEn) {
+        $val = Get-EnTrans $key
+        $newEntries += "    `"$key`": `"$val`""
+    }
+    $toAdd = "," + [Environment]::NewLine + ($newEntries -join "," + [Environment]::NewLine)
+    
+    $lastBraceIndex = $enContent.LastIndexOf("}")
+    if ($lastBraceIndex -ge 0) {
+        $enContent = $enContent.Substring(0, $lastBraceIndex) + $toAdd + [Environment]::NewLine + "}"
+        Set-Content -Path $enPath -Value $enContent -Encoding UTF8
+        Write-Host "Added $($missingEn.Count) keys to en.json"
+    }
+} else {
+    Write-Host "No missing keys in EN"
+}
+
+# Add to CN
+if ($missingCn.Count -gt 0) {
+    $newEntries = @()
+    foreach ($key in $missingCn) {
+        $val = Get-CnTrans $key
+        $newEntries += "    `"$key`": `"$val`""
+    }
+    $toAdd = "," + [Environment]::NewLine + ($newEntries -join "," + [Environment]::NewLine)
+    
+    $lastBraceIndex = $cnContent.LastIndexOf("}")
+    if ($lastBraceIndex -ge 0) {
+        $cnContent = $cnContent.Substring(0, $lastBraceIndex) + $toAdd + [Environment]::NewLine + "}"
+        Set-Content -Path $cnPath -Value $cnContent -Encoding UTF8
+        Write-Host "Added $($missingCn.Count) keys to zh-cn.json"
+    }
+} else {
+    Write-Host "No missing keys in CN"
+}
diff --git a/scripts/find_missing_keys.ps1 b/scripts/find_missing_keys.ps1
new file mode 100644
index 0000000..b33bf47
--- /dev/null
+++ b/scripts/find_missing_keys.ps1
@@ -0,0 +1,28 @@
+$javaFiles = Get-ChildItem -Path "src/main/java" -Recurse -Filter "*.java"
+$foundKeys = @()
+foreach ($file in $javaFiles) {
+    $content = Get-Content $file.FullName
+    $matches = [regex]::Matches($content, 'response\.[a-zA-Z0-9_]+')
+    foreach ($match in $matches) {
+        $foundKeys += $match.Value
+    }
+}
+$foundKeys = $foundKeys | Sort-Object | Get-Unique
+
+# Exclude technical calls like response.getOutputStream, response.setContentType, etc.
+$exclude = @("response.getOutputStream", "response.setContentType", "response.setCharacterEncoding", "response.setHeader", "response.sendRedirect", "response.getWriter", "response.addCookie", "response.setStatus", "response.reset")
+$foundKeys = $foundKeys | Where-Object { $exclude -notcontains $_ }
+
+$enContent = Get-Content "src/main/webapp/static/i18n/en.json" -Raw
+$enKeys = [regex]::Matches($enContent, '"(response\.[^"]+)"') | ForEach-Object { $_.Groups[1].Value }
+
+$cnContent = Get-Content "src/main/webapp/static/i18n/zh-cn.json" -Raw
+$cnKeys = [regex]::Matches($cnContent, '"(response\.[^"]+)"') | ForEach-Object { $_.Groups[1].Value }
+
+$missingEn = $foundKeys | Where-Object { $enKeys -notcontains $_ }
+$missingCn = $foundKeys | Where-Object { $cnKeys -notcontains $_ }
+
+Write-Output "Missing in EN:"
+$missingEn
+Write-Output "Missing in CN:"
+$missingCn
diff --git a/scripts/mapping.json b/scripts/mapping.json
new file mode 100644
index 0000000..cdd713b
--- /dev/null
+++ b/scripts/mapping.json
@@ -0,0 +1,37 @@
+{
+    "add": "鏂板", "delete": "鍒犻櫎", "update": "淇敼", "edit": "缂栬緫", 
+    "list": "鍒楄〃", "export": "瀵煎嚭", "detail": "璇︽儏", "query": "鏌ヨ",
+    "import": "瀵煎叆", "success": "鎴愬姛", "failed": "澶辫触", "error": "閿欒",
+    "mat": "鐗╂枡", "user": "鐢ㄦ埛", "role": "瑙掕壊", "menu": "鑿滃崟",
+    "dept": "閮ㄩ棬", "area": "搴撳尯", "loc": "搴撲綅", "node": "璐т綅",
+    "order": "鍗曟嵁", "task": "浠诲姟", "work": "浣滀笟", "log": "鏃ュ織",
+    "station": "绔欏彴", "zone": "搴撳尯", "warehouse": "浠撳簱", "whs": "浠撳簱",
+    "stock": "搴撳瓨", "inbound": "鍏ュ簱", "outbound": "鍑哄簱", "print": "鎵撳嵃",
+    "check": "鐩樼偣", "audit": "瀹℃牳", "cancel": "鍙栨秷", "close": "鍏抽棴",
+    "enable": "鍚敤", "disable": "绂佺敤", "pda": "PDA", "search": "鎼滅储",
+    "find": "鏌ユ壘", "count": "鏁伴噺", "param": "鍙傛暟", "exists": "宸插瓨鍦�",
+    "empty": "涓虹┖", "required": "蹇呭~", "permission": "鏉冮檺", "auth": "璁よ瘉",
+    "login": "鐧诲綍", "logout": "鐧诲嚭", "password": "瀵嗙爜", "reset": "閲嶇疆",
+    "group": "缁�", "type": "绫诲瀷", "status": "鐘舵��", "history": "鍘嗗彶",
+    "config": "閰嶇疆", "system": "绯荤粺", "data": "鏁版嵁", "file": "鏂囦欢",
+    "download": "涓嬭浇", "upload": "涓婁紶", "template": "妯℃澘", "preview": "棰勮",
+    "start": "鍚姩", "stop": "鍋滄", "pause": "鏆傚仠", "resume": "鎭㈠",
+    "finish": "瀹屾垚", "submit": "鎻愪氦", "reject": "鎷掔粷", "approve": "閫氳繃",
+    "batch": "鎵归噺", "all": "鍏ㄩ儴", "info": "淇℃伅", "msg": "娑堟伅",
+    "code": "缂栫爜", "name": "鍚嶇О", "desc": "鎻忚堪", "memo": "澶囨敞",
+    "tree": "鏍�", "chart": "鍥捐〃", "report": "鎶ヨ〃", "home": "棣栭〉",
+    "main": "涓�", "sub": "瀛�", "parent": "鐖�", "child": "瀛�",
+    "init": "鍒濆鍖�", "sync": "鍚屾", "refresh": "鍒锋柊", "load": "鍔犺浇",
+    "save": "淇濆瓨", "create": "鍒涘缓", "remove": "绉婚櫎", "clear": "娓呯┖",
+    "select": "閫夋嫨", "confirm": "纭", "cancel": "鍙栨秷", "ok": "纭畾",
+    "yes": "鏄�", "no": "鍚�", "true": "鐪�", "false": "鍋�",
+    "wrk": "浣滀笟", "mast": "涓绘。", "detl": "鏄庣粏", "execute": "鎵ц",
+    "lastno": "娴佹按鍙�", "stk": "搴撳瓨", "plcm": "浣嶇疆", "crn": "鍫嗗灈鏈�",
+    "devp": "璁惧", "dev": "璁惧", "err": "寮傚父", "opt": "鎿嶄綔",
+    "plc": "PLC", "wcs": "WCS", "wms": "WMS", "mes": "MES",
+    "sap": "SAP", "erp": "ERP", "agv": "AGV", "rgv": "RGV",
+    "led": "LED", "rfid": "RFID", "barcode": "鏉$爜", "qrcode": "浜岀淮鐮�",
+    "label": "鏍囩", "print": "鎵撳嵃", "scan": "鎵弿", "read": "璇诲彇",
+    "write": "鍐欏叆", "open": "鎵撳紑", "close": "鍏抽棴", "connect": "杩炴帴",
+    "disconnect": "鏂紑", "send": "鍙戦��", "receive": "鎺ユ敹", "request": "璇锋眰"
+}
diff --git a/scripts/update_i18n.ps1 b/scripts/update_i18n.ps1
new file mode 100644
index 0000000..1ac028c
--- /dev/null
+++ b/scripts/update_i18n.ps1
@@ -0,0 +1,146 @@
+
+# Set encoding to UTF8
+$OutputEncoding = [System.Text.Encoding]::UTF8
+
+# Paths
+$root = "f:\workFile\2026.1.12yuedan\zy-asrs"
+$enPath = "$root\src\main\webapp\static\i18n\en.json"
+$cnPath = "$root\src\main\webapp\static\i18n\zh-cn.json"
+$mapPath = "$root\scripts\mapping.json"
+$javaPath = "$root\src\main\java"
+
+# 1. Load Mapping
+if (Test-Path $mapPath) {
+    $mapContent = Get-Content $mapPath -Raw -Encoding UTF8 | ConvertFrom-Json
+} else {
+    Write-Host "Mapping file not found!"
+    $mapContent = $null
+}
+
+# 2. Scan Java Files for keys
+Write-Host "Scanning Java files..."
+$javaFiles = Get-ChildItem -Path $javaPath -Recurse -Filter "*.java"
+$foundKeys = @()
+foreach ($file in $javaFiles) {
+    $content = Get-Content $file.FullName
+    # Regex to capture response.xxx
+    # Matches response. followed by letters, numbers, underscores, dots
+    $matches = [regex]::Matches($content, 'response\.[a-zA-Z0-9_]+')
+    foreach ($match in $matches) {
+        $foundKeys += $match.Value
+    }
+}
+
+# Manual keys mentioned by user
+$manualKeys = @("response.mat_list", "response.menu_list", "response.mat_delete", "response.mat_update", "response.user_detail")
+$foundKeys += $manualKeys
+
+# Unique and Sort
+$foundKeys = $foundKeys | Sort-Object | Get-Unique
+
+# Exclude technical calls (heuristic)
+$exclude = @("response.getOutputStream", "response.setContentType", "response.setCharacterEncoding", "response.setHeader", "response.sendRedirect", "response.getWriter", "response.addCookie", "response.setStatus", "response.reset", "response.isSuccessful", "response.getStatus", "response.put")
+$foundKeys = $foundKeys | Where-Object { $exclude -notcontains $_ }
+
+Write-Host "Found $($foundKeys.Count) unique 'response.*' keys."
+
+# Helper Functions
+function Get-EnTrans($key) {
+    $parts = $key.Replace("response.", "").Split("_")
+    $text = $parts | ForEach-Object { $_.Substring(0,1).ToUpper() + $_.Substring(1) }
+    return $text -join " "
+}
+
+function Get-CnTrans($key) {
+    $keyRaw = $key.Replace("response.", "")
+    $parts = $keyRaw.Split("_")
+    $trans = ""
+    foreach ($part in $parts) {
+        $found = $false
+        if ($mapContent -ne $null) {
+            if ($mapContent.PSObject.Properties.Name -contains $part) {
+                $trans += $mapContent.$part
+                $found = $true
+            }
+        }
+        
+        if (-not $found) {
+             if ($part.Length -gt 0) {
+                 # Fallback: capitalize
+                 # Or maybe leave as English if no mapping? 
+                 # User wants Chinese, but better English than nothing.
+                 # But we try to map.
+                 # If valid mapping is missing, we might want to flag it?
+                 # For now, just Capitalize
+                 $trans += $part.Substring(0,1).ToUpper() + $part.Substring(1)
+             }
+        }
+    }
+    return $trans
+}
+
+function Process-JsonFile($path, $lang) {
+    Write-Host "Processing $path ..."
+    $jsonContent = Get-Content $path -Raw -Encoding UTF8 | ConvertFrom-Json
+    
+    # Convert to hashtable for easier manipulation if possible, 
+    # but ConvertFrom-Json returns PSCustomObject.
+    # We will build a new Ordered Dictionary to store results.
+    
+    $newDict = [Ordered]@{}
+    
+    # Copy existing keys
+    foreach ($prop in $jsonContent.PSObject.Properties) {
+        $newDict[$prop.Name] = $prop.Value
+    }
+    
+    # Update/Add keys
+    $addedCount = 0
+    $updatedCount = 0
+    
+    foreach ($key in $foundKeys) {
+        $val = ""
+        if ($lang -eq "en") {
+            $val = Get-EnTrans $key
+        } else {
+            $val = Get-CnTrans $key
+        }
+        
+        if ($newDict.Contains($key)) {
+            # Check if empty
+            if ([string]::IsNullOrEmpty($newDict[$key])) {
+                $newDict[$key] = $val
+                $updatedCount++
+                Write-Host "  Updated empty key: $key -> $val"
+            }
+        } else {
+            # Add new
+            $newDict[$key] = $val
+            $addedCount++
+            Write-Host "  Added new key: $key -> $val"
+        }
+    }
+    
+    Write-Host "  Added: $addedCount, Updated: $updatedCount"
+    
+    # Sort keys
+    $sortedDict = [Ordered]@{}
+    $keys = $newDict.Keys | Sort-Object
+    foreach ($k in $keys) {
+        $sortedDict[$k] = $newDict[$k]
+    }
+    
+    # Convert back to JSON
+    $jsonOutput = $sortedDict | ConvertTo-Json -Depth 100
+    
+    # Unescape Unicode
+    $jsonOutput = [regex]::Replace($jsonOutput, "\\u([0-9a-fA-F]{4})", { param($m) [char][int]::Parse($m.Groups[1].Value, [System.Globalization.NumberStyles]::HexNumber) })
+    
+    # Save
+    $jsonOutput | Set-Content -Path $path -Encoding UTF8
+}
+
+Process-JsonFile $enPath "en"
+Process-JsonFile $cnPath "cn"
+
+Write-Host "Done."
diff --git a/src/main/java/com/zy/asrs/controller/MobileController.java b/src/main/java/com/zy/asrs/controller/MobileController.java
index b7c5c30..102aa24 100644
--- a/src/main/java/com/zy/asrs/controller/MobileController.java
+++ b/src/main/java/com/zy/asrs/controller/MobileController.java
@@ -160,6 +160,40 @@
         return R.ok("response.comb_success");
     }
 
+    @RequestMapping("/cartonScanReplace/auth")
+    @ManagerAuth(memo = "response.carton_scan")
+    public R cartonScanReplace(@RequestBody ScanParam scanParam){
+        List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("barcode",scanParam.getCartonLabel()));
+        if (wrkDetls.isEmpty()) {
+            return R.error("response.no_data");
+        }
+        WrkDetl wrkDetl = wrkDetls.get(0);
+        return R.ok("response.scan_success").add(wrkDetl);
+
+    }
+    @RequestMapping("/labelReplace/auth")
+    @ManagerAuth(memo = "response.carton_scan_save")
+    public R cartonScanReplaceSave(@RequestBody ReplaceBarcodeParam replaceBarcodeParam) {
+        if (replaceBarcodeParam == null || Cools.isEmpty(replaceBarcodeParam.getReplaceParam())) {
+            return R.error("PARAM IS NULL");
+        }
+        for (ReplaceBarcodeParam.CombinedData param : replaceBarcodeParam.getReplaceParam()) {
+            WrkDetl wrkDetl = wrkDetlService.selectOne(
+                    new EntityWrapper<WrkDetl>()
+                            .eq("order_no", param.getOrderNo())
+                            .eq("barcode", param.getBarcode())
+            );
+            if (wrkDetl == null) {
+                return R.error("DETL IS NULL, barcode=" + param.getBarcode());
+            }
+            if (!wrkDetlService.updateBuyerLabel(param.getOrderNo(), param.getBuyerLabelBarcode(),param.getBarcode())) {
+                return R.error("Failed to update, barcode=" + param.getBarcode());
+            }
+        }
+        return R.ok("response.replace_success");
+    }
+
+
     @RequestMapping("/cartonScan/auth")
     @ManagerAuth(memo = "response.carton_scan")
     public R cartonScan(@RequestBody ScanParam scanParam){
diff --git a/src/main/java/com/zy/asrs/entity/param/ReplaceBarcodeParam.java b/src/main/java/com/zy/asrs/entity/param/ReplaceBarcodeParam.java
new file mode 100644
index 0000000..ea30ccd
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/ReplaceBarcodeParam.java
@@ -0,0 +1,22 @@
+package com.zy.asrs.entity.param;
+
+import com.zy.common.model.LocDto;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ReplaceBarcodeParam {
+
+    private List<CombinedData> replaceParam;
+
+    @Data
+    public static class CombinedData {
+        private String barcode;            // 鍐呴儴绠辨潯鐮�
+        private Double qty;
+        private Double ctn;
+        private String orderNo;
+        private String buyerLabelBarcode;  // 瀹㈡埛鏍囩
+    }
+}
+
diff --git a/src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java b/src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java
index 2d016a8..b1d34ab 100644
--- a/src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java
+++ b/src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java
@@ -26,6 +26,7 @@
 
     List<WrkDetl> selectAndLogByOrderNo(String orderNo);
 
+    int updateBuyerLabel(@Param("orderNo")String orderNo, @Param("buyerLabel")String buyerLabel,@Param("barcode")String barcode);
     int updateInspect( @Param("wrkNo")Integer wrkNo, @Param("matnr")String matnr, @Param("batch")String batch);
 
     List<WrkDetl> selectPakoutQuery(@Param("staNo")Integer staNo, @Param("matnr")String matnr);
diff --git a/src/main/java/com/zy/asrs/service/WrkDetlService.java b/src/main/java/com/zy/asrs/service/WrkDetlService.java
index 71bd32e..6325e2d 100644
--- a/src/main/java/com/zy/asrs/service/WrkDetlService.java
+++ b/src/main/java/com/zy/asrs/service/WrkDetlService.java
@@ -19,6 +19,7 @@
     boolean updateAnfme(Double anfme, Integer wrkNo, String matnr, String batch);
     boolean updateAnfme(Double anfme, Integer wrkNo, String matnr, String batch,String barcode);
 
+    boolean updateBuyerLabel(String orderNo,String buyerLabel,String barcode);
 
     List<WrkDetl> selectAndLogByOrderNo(String orderNo);
     List<WrkDetl> findByBarcode(String barcode);
diff --git a/src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java
index 299f650..11e56e7 100644
--- a/src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java
@@ -9,6 +9,7 @@
 import com.zy.asrs.service.MatService;
 import com.zy.asrs.service.WrkDetlService;
 import com.zy.common.model.DetlDto;
+import com.zy.common.utils.HttpHandler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -78,6 +79,10 @@
             return baseMapper.updateAnfme(anfme, wrkNo, matnr, batch,barcode) > 0;
         }
     }
+    @Override
+    public  boolean updateBuyerLabel(String orderNo,String buyerLabel,String barcode){
+        return this.baseMapper.updateBuyerLabel(orderNo, buyerLabel,barcode) > 0;
+    }
 
     @Override
     public List<WrkDetl> selectAndLogByOrderNo(String orderNo) {
diff --git a/src/main/resources/mapper/WrkDetlMapper.xml b/src/main/resources/mapper/WrkDetlMapper.xml
index be54187..5894eba 100644
--- a/src/main/resources/mapper/WrkDetlMapper.xml
+++ b/src/main/resources/mapper/WrkDetlMapper.xml
@@ -88,6 +88,12 @@
         and matnr = #{matnr}
         <include refid="batchSeq"></include>
     </update>
+    <update id="updateBuyerLabel">
+        update asr_wrk_detl
+        set memo = #{buyerLabel}
+        where order_no = #{orderNo}
+        and barcode = #{barcode}
+    </update>
 
     <select id="selectAndLogByOrderNo" resultMap="BaseResultMap">
         select * from asr_wrk_detl where order_no = #{orderNo}
diff --git a/src/main/webapp/static/i18n/en.json b/src/main/webapp/static/i18n/en.json
index cdc9d2d..d4dbf51 100644
--- a/src/main/webapp/static/i18n/en.json
+++ b/src/main/webapp/static/i18n/en.json
@@ -579,6 +579,7 @@
     "response.code_or_name_exists":  "Code or name already exists",
     "response.comb_success":  "Comb Success",
     "response.scan_success":  "Scan Success",
+    "response.replace_success":  "Replace Success",
     "response.confirm_complete":  "Confirm Complete",
     "response.confirm_picking_outbound_failed":  "Confirm Picking Outbound Failed",
     "response.crane_add":  "Crane Add",
diff --git a/src/main/webapp/static/i18n/en/common.json b/src/main/webapp/static/i18n/en/common.json
new file mode 100644
index 0000000..fbfc367
--- /dev/null
+++ b/src/main/webapp/static/i18n/en/common.json
@@ -0,0 +1,483 @@
+{
+    "status_desc": "Status Description",
+    "wrk_status_0": "0.Pending Receive",
+    "wrk_status_1": "1.Received",
+    "wrk_status_2": "2.Task Started",
+    "wrk_status_3": "3.Pickup Completed",
+    "wrk_status_4": "4.Inbound Completed",
+    "wrk_status_5": "5.Inventory Updated",
+    "wrk_status_6": "6.Task Interrupted",
+    "wrk_status_7": "7.Drop-off Completed",
+    "wrk_status_11": "11.Outbound ID Generated",
+    "wrk_status_12": "12.Crane Outbound In Progress",
+    "wrk_status_13": "13.Crane Empty Outbound Error",
+    "wrk_status_14": "14.Outbound Unconfirmed",
+    "wrk_status_15": "15.Outbound Update Completed",
+    "display_mode": "Display Mode",
+    "view_by_row": "View by Row",
+    "view_by_layer": "View by Layer",
+    "enable_selection": "Enable Selection",
+    "disable_selection": "Disable Selection",
+    "assign_zone": "Assign Zone",
+    "zone_legend": "Zone Legend",
+    "selection_mode_tip": "Selection mode enabled, please drag to select on the location map",
+    "please_select_zone": "Please select a zone",
+    "zone_color": "Zone Color",
+    "assign_zone_and_color": "Assign Zone and Color",
+    "confirm": "Confirm",
+    "cancel": "Cancel",
+    "cancel_selection": "Cancel Selection",
+    "assign_success": "Assignment successful",
+    "operation_failed": "Operation failed",
+    "fetch_zone_list_failed": "Failed to fetch zone list",
+    "modify_zone_color": "Modify Zone Color",
+    "zone_name": "Zone Name",
+    "select_color": "Select Color",
+    "save": "Save",
+    "color_updated": "Color updated",
+    "update_failed": "Update failed",
+    "load_failed": "Load failed",
+    "language": "Language",
+    "license_validity_prefix": "Temporary license valid for: ",
+    "license_validity_suffix": " days",
+    "basic_info": "Basic Information",
+    "logout": "Log Out",
+    "home": "Home",
+    "_comment_home": "Home Tab Bar",
+    "涓婚〉": "Home",
+    "鎺у埗鍙�": "Dashboard",
+    "鍒嗘瀽椤�": "Analytics",
+    "搴撲綅鐑偣鍥�": "Location Heatmap",
+    "鍩虹鏁版嵁": "Master Data",
+    "鍟嗗搧妗f": "Item Master",
+    "宸ヤ綔鐘舵��": "Task Status",
+    "鍏ュ嚭搴撶被鍨�": "Transaction Types",
+    "搴撲綅鐘舵��": "Location Status",
+    "搴撲綅绫诲瀷绠$悊": "LocType Management",
+    "宸ヤ綔搴忓彿鏌ヨ": "Task Number Query",
+    "搴撲綅鎺掑彿鍒嗛厤": "Location Slot Query",
+    "褰掔被绠$悊": "Category Management",
+    "搴撳尯绠$悊": "Zone Management",
+    "璺緞绔欑偣璁剧疆": "Path & Station Setup",
+    "搴撳瓨绠$悊": "Inventory Management",
+    "搴撲綅鏌ヨ": "Location Inquiry",
+    "搴撳瓨鏄庣粏绠$悊": "Inventory Detail",
+    "搴撳瓨璋冩暣": "Inventory Adjustment",
+    "搴撳瓨鏄庣粏缁熻": "Inventory Summary",
+    "鍏ュ嚭搴撲綔涓�": "Out & In Operations",
+    "鍏ュ簱浣滀笟": "Inbound Operations",
+    "鍑哄簱浣滀笟": "Outbound Operations",
+    "鐩樼偣鍑哄簱": "Cycle Count Outbound",
+    "搴撲綅绉昏浆": "Location Transfer",
+    "绌烘澘鍑哄簱": "Empty Pallet Outbound",
+    "宸ヤ綔妗g鐞�": "Work Orders",
+    "宸ヤ綔妗f煡璇㈢淮鎶�": "Work Order Query",
+    "宸ヤ綔妗f槑缁嗘煡璇�": "Work Order Details",
+    "宸ヤ綔鍘嗗彶妗f煡璇�": "Work Order History",
+    "宸ヤ綔鏄庣粏鍘嗗彶妗f煡璇�": "Work Order Detail History",
+    "work_order_detail_history": "Work Order Detail History",
+    "鍏ュ簱閫氱煡妗�": "Inbound Notice",
+    "鍏ュ簱閫氱煡鍘嗗彶妗�": "Inbound Notice History",
+    "璁㈠崟绯荤粺": "Order System",
+    "鍗曟嵁绠$悊": "Order Management",
+    "璁㈠崟鍑哄簱": "Order Outbound",
+    "璁㈠崟鐘舵��": "Order Status",
+    "鍗曟嵁绫诲瀷": "Order Types",
+    "璁惧缁存姢": "Equipment Maintenance",
+    "搴撲綅绠$悊": "Location Management",
+    "绔欑偣绠$悊": "Station Management",
+    "鏃ュ織缁熻": "Logs & Stats",
+    "搴撳瓨璋冩暣璁板綍": "Inventory Adjustments",
+    "涓夋柟鎺ュ彛缁熻": "3rd-Party API Logs",
+    "寮傚父宸ヤ綔妗�": "Exception Work Orders",
+    "搴撲綅浣跨敤鐜囩粺璁�": "Location Utilization",
+    "搴撳瓨鍦ㄥ簱鏃堕棿缁熻": "Inventory Age",
+    "鏃ュ叆鍑哄簱娆℃暟缁熻": "Daily Transactions",
+    "鏃ュ叆搴撴槑缁嗘煡璇�": "Inbound Details",
+    "鏃ュ嚭搴撴槑缁嗘煡璇�": "Outbound Details",
+    "宸ヤ綔妗g淮鎶ゆ棩蹇�": "Work Maintenance Log",
+    "寮�鍙戜笓鐢�": "Developer Tools",
+    "鑿滃崟鍒楄〃": "Menu List",
+    "鏉冮檺鎺у埗": "Permission Control",
+    "鎺ュ彛鏂囨。": "API Documentation",
+    "鍑瘉璁板綍": "Credential Records",
+    "绯荤粺閰嶇疆": "System Configuration",
+    "绯荤粺绠$悊": "System Management",
+    "绯荤粺鐢ㄦ埛": "System Users",
+    "瑙掕壊绠$悊": "Role Management",
+    "鎿嶄綔鏃ュ織": "Operation Log",
+    "涓汉璁剧疆": "Personal Settings",
+    "鍩烘湰璧勬枡": "Basic Information",
+    "鍙鍖�": "Visualization",
+    "渚ц竟浼哥缉": "Toggle Side",
+    "鍒锋柊": "Refresh",
+    "鍏ㄥ睆": "Full Screen",
+    "涓婚": "Theme",
+    "鍏抽棴褰撳墠": "Close Current",
+    "鍏抽棴鍏朵粬": "Close Others",
+    "鍏抽棴鎵�鏈�": "Close All",
+    "鍏抽棴褰撳墠鏍囩椤�": "Close Current Tab",
+    "鍏抽棴鍏朵粬鏍囩椤�": "Close Other Tabs",
+    "鍏抽棴鎵�鏈夋爣绛鹃〉": "Close All Tabs",
+    "涓婚〉涓嶈兘鍏抽棴": "Home page cannot be closed",
+    "棣栭〉": "Home Page",
+    "搴撳瓨婊炵暀鏃堕棿缁熻琛�": "Stock Retention Time Statistics",
+    "搴撲綅浣跨敤姣斾緥": "Location Usage Ratio",
+    "搴撲綅鍗犳瘮": "Location Percentage",
+    "鏃ュ叆鍑哄簱鏁伴噺": "Daily In/Out Quantity",
+    "鍏鍑哄簱鏁伴噺": "In/Out Quantity",
+    "浠撳偍绠$悊绯荤粺": "WMS",
+    "璇烽�夋嫨鎮ㄨ浣跨敤鐨勬ā鍧�": "Please select the module you want to use",
+    "杩愯浠诲姟": "Running Tasks",
+    "搴撳瓨鏄庣粏": "Inventory Details",
+    "_comment_common": "Common Table Columns",
+    "鍟嗗搧缂栧彿_鍝佸彿": "Item No.",
+    "鍟嗗搧鍚嶇О_鍝佸悕": "Item Name",
+    "瑙勬牸": "Spec",
+    "浠g爜": "Code",
+    "棰滆壊": "Color",
+    "鍝佺墝": "Brand",
+    "鍗曚綅": "Unit",
+    "鍗曚环": "Price",
+    "sku": "SKU",
+    "鍗曚綅閲�": "Unit Qty",
+    "鏉$爜": "Barcode",
+    "浜у湴": "Origin",
+    "鍘傚": "Manufacturer",
+    "鐢熶骇鏃ユ湡": "Mfg Date",
+    "鍝侀」鏁�": "Item Count",
+    "瀹夊叏搴撳瓨閲�": "Safety Stock",
+    "鍗曠鍑�閲�": "Net Weight/Box",
+    "鍗曠姣涢噸": "Gross Weight/Box",
+    "鍗曠浣撶Н": "Volume/Box",
+    "绠卞瓙灏哄": "Box Size",
+    "渚涘簲鍟�": "Supplier",
+    "渚涘簲鍟嗙紪鐮�": "Supplier Code",
+    "鏄惁鎵规": "Batch Managed",
+    "淇濊川鏈�": "Shelf Life",
+    "棰勮澶╂暟": "Warning Days",
+    "鍒惰喘": "Make/Buy",
+    "瑕佹眰妫�楠�": "Inspection Reqd",
+    "鍗遍櫓鍝�": "Hazardous",
+    "淇敼浜哄憳": "Updated By",
+    "淇敼鏃堕棿": "Updated Time",
+    "澶囨敞": "Remark",
+    "鍗曟嵁缂栧彿": "Order No.",
+    "鎵瑰彿": "Batch No.",
+    "鏁伴噺": "Quantity",
+    "鎵樼洏鏉$爜": "Pallet Barcode",
+    "鍏ュ簱鏃堕棿": "Inbound Time",
+    "婊炵暀澶╂暟": "Retention Days",
+    "搴撲綅鍙�": "Location No.",
+    "鎵樼洏鐮�": "Pallet Code",
+    "鍟嗗搧缂栧彿": "Item No.",
+    "鍟嗗搧鍚嶇О": "Item Name",
+    "璇疯緭鍏�": "Please enter",
+    "鎼滅储": "Search",
+    "閲嶇疆": "Reset",
+    "瀵煎嚭": "Export",
+    "璇︽儏": "Detail",
+    "搴撻緞_澶�": "Age(Days)",
+    "no_data": "No Data",
+    "start_end_time": "Start / End Time",
+    "add": "Add",
+    "delete": "Delete",
+    "edit": "Edit",
+    "data_status": "Data Status",
+    "normal": "Normal",
+    "status_disabled": "Disabled",
+    "locked": "Locked",
+    "io_status": "Transaction Status",
+    "inbound": "Inbound",
+    "pending_inbound": "Pending Inbound",
+    "confirm_generate_task": "Confirm Task Generation",
+    "select_one_data": "Select One Record",
+    "confirm_delete_data": "Confirm Delete Record",
+    "confirm_delete_prefix": "Are you sure to delete ",
+    "confirm_delete_suffix": " record(s)?",
+    "this": "this",
+    "account": "Account",
+    "username": "Username",
+    "password": "Password",
+    "role": "Role",
+    "age_days": "Inventory Age(Days)",
+    "product_name": "Item Name",
+    "order_no": "Order No.",
+    "batch_no": "Batch No.",
+    "unit_qty": "Unit Qty",
+    "spec": "Spec",
+    "code": "Code",
+    "color": "Color",
+    "brand": "Brand",
+    "origin": "Origin",
+    "manufacturer": "Manufacturer",
+    "mfg_date": "Mfg Date",
+    "item_count": "Item Count",
+    "safety_stock": "Safety Stock",
+    "net_weight_box": "Net Weight/Box",
+    "gross_weight_box": "Gross Weight/Box",
+    "volume_box": "Volume/Box",
+    "box_size": "Box Size",
+    "supplier": "Supplier",
+    "supplier_code": "Supplier Code",
+    "batch_managed": "Batch Managed",
+    "shelf_life": "Shelf Life",
+    "warning_days": "Warning Days",
+    "make_buy": "Make/Buy",
+    "inspection_reqd": "Inspection Reqd",
+    "hazardous": "Hazardous",
+    "confirm_export_excel": "Confirm Export to Excel",
+    "no_data_found": "No Data Found",
+    "creator_detail": "Creator Details",
+    "modifier_detail": "Modifier Details",
+    "please_select_data": "please select data",
+    "pallet_barcode": "Pallet Code",
+    "product_code": "Item No.",
+    "location_no": "Location No.",
+    "search": "search",
+    "reset": "reset",
+    "export": "export",
+    "exporting": "Exporting...",
+    "detail": "Detail",
+    "modifier": "Modifier",
+    "modify_time": "Modify Time",
+    "prompt": "Prompt",
+    "info": "Info",
+    "id": "ID",
+    "material": "Material",
+    "material_desc": "Material Desc",
+    "status": "Status",
+    "remark": "Remark",
+    "add_time": "Add Time",
+    "creator": "Creator",
+    "close": "Close",
+    "modify": "Modify",
+    "warm_prompt_prefix": "Warm Prompt: Please fill in the information carefully, ",
+    "warm_prompt_suffix": "is mandatory.",
+    "total_prefix": "Total ",
+    "total_suffix": " items",
+    "jump_to": "Go to ",
+    "page": " page",
+    "items_per_page": " items/page",
+    "running": "Running",
+    "pending": "Pending",
+    "inbound_notice_no": "Inbound Notice No",
+    "input_placeholder": "Please input...",
+    "work_time": "Work Time",
+    "barcode": "Barcode",
+    "work_no": "Work No",
+    "work_status": "Work Status",
+    "crane_no": "Crane No",
+    "crane": "Crane",
+    "increase_priority": "Increase Priority",
+    "decrease_priority": "Decrease Priority",
+    "pre_existing": "Pre-Existing",
+    "empty_op": "Empty Op",
+    "pick": "Pick",
+    "count": "Count",
+    "complete": "Complete",
+    "cancel": "Cancel",
+    "transaction_type": "Transaction Type",
+    "priority": "Priority",
+    "source_station": "Source Station",
+    "target_station": "Target Station",
+    "source_location": "Source Location",
+    "target_location": "Target Location",
+    "picking": "Picking",
+    "exit": "Exit",
+    "warehouse_no": "Warehouse No",
+    "transfer_req_no": "Transfer Req No",
+    "item_no": "Item No",
+    "material_label_id": "Material Label ID",
+    "factory": "Factory",
+    "quantity": "Quantity",
+    "unit": "Unit",
+    "user_id": "User ID",
+    "empty_pallet": "Empty Pallet",
+    "work_time": "Work Time",
+    "crane_start_time": "Crane Start Time",
+    "crane_end_time": "Crane End Time",
+    "picking_time": "Picking Time",
+    "full_pallet": "Full Pallet",
+    "operation": "Operation",
+    "current_workflow_detail": "Material details for current workflow",
+    "confirm_cancel_work_order": "Confirm cancel this work order?",
+    "confirm_complete_work_order": "Confirm complete this work order?",
+    "confirm_pick_work_order": "Pick inbound this work order?",
+    "confirm_pre_existing_exception": "Pre-existing exception occurred. To re-inbound, ensure cargo is at crane outbound station!",
+    "confirm_cancel_erp_order": "Current task linked to ERP sales order. Cancellation will regenerate outbound task. Continue?",
+    "confirm_export": "Confirm export to Excel?",
+    "confirm_empty_op_exception": "Empty operation exception! Continue?",
+    "work_order_detail": "Work Order Detail",
+    "location_type": "Location Type",
+    "row": "Row",
+    "bay": "Bay",
+    "level": "Level",
+    "group": "Group",
+    "init": "Init",
+    "please_enter_password_reset_location": "Please enter password to reset location",
+    "init_location": "Initialize Location",
+    "password_error": "Password Error",
+    "location_detail": "Location Detail",
+    "modify_detail": "Modification Detail",
+    "create_detail": "Creation Detail",
+    "high_low_type": "High/Low Type",
+    "width_type": "Width Type",
+    "weight_type": "Weight Type",
+    "delete_location": "Delete Location",
+    "delete_keep": "Delete|Keep",
+    "start_end_row": "Start/End Row",
+    "start_end_bay": "Start/End Bay",
+    "start_end_level": "Start/End Level",
+    "crane_amount": "Crane Amount",
+    "start_crane": "Start Crane",
+    "low_location": "Low Location",
+    "high_location": "High Location",
+    "middle_location": "Middle Location",
+    "narrow_location": "Narrow Location",
+    "wide_location": "Wide Location",
+    "light_location": "Light Location",
+    "heavy_location": "Heavy Location",
+    "unknown": "Unknown",
+    "standard_crane_whs": "Standard Crane Whs",
+    "flat_whs": "Flat Whs",
+    "shuttle_board": "Shuttle Board",
+    "four_way_vehicle": "Four-way Vehicle",
+    "agv": "AGV",
+    "warm_prompt_clear_inventory": "Warm Prompt: Clearing inventory when modifying to empty location",
+    "绂佺敤搴撲綅": "Disabled Location",
+    "鍦ㄥ簱搴撲綅": "Occupied Location",
+    "绌哄簱浣�": "Empty Location",
+    "浣跨敤搴撲綅": "Used Location",
+    "鍏ュ簱鏁伴噺": "Inbound Quantity",
+    "鍑哄簱鏁伴噺": "Outbound Quantity",
+    "classification": "Type",
+    "stock_upper_limit": "Stock Max",
+    "stock_lower_limit": "Stock Min",
+    "stock_age_upper_limit_days": "Max Stock Age (Days)",
+    "area": "Area",
+    "please_select_print_data": "Please select data to print",
+    "batch_print_count": "Batch Print [Count: {{count}}]",
+    "category_cannot_be_empty": "Category cannot be empty",
+    "confirm_sync_file": "Confirm sync file [{{filename}}]?",
+    "template_1": "Template 1",
+    "template_2": "Template 2",
+    "template_3": "Template 3",
+    "print_preview": "Print Preview",
+    "please_input_item_no": "Enter Item No.",
+    "please_input_item_name": "Enter Item Name",
+    "please_input_item_spec": "Enter Item Spec",
+    "batch_print": "Batch Print",
+    "print": "Print",
+    "select_template": "Select Template",
+    "item": "Item",
+    "item_code": "Item Code",
+    "item_name": "Item Name",
+    "item_spec": "Item Spec",
+    "data_sync": "Sync Data",
+    "io_type_code": "Transaction Type Code",
+    "io_type_desc": "Transaction Type Description",
+    "io_type_1": "1.Inbound",
+    "io_type_3": "3.Station to Station",
+    "io_type_6": "6.Exit on Device",
+    "io_type_10": "10.Empty Pallet Inbound",
+    "io_type_11": "11.Bin Transfer",
+    "io_type_53": "53.Picking Re-inbound",
+    "io_type_54": "54.Merge Re-inbound",
+    "io_type_57": "57.Cycle Count Re-inbound",
+    "io_type_101": "101.Outbound",
+    "io_type_103": "103.Picking Outbound",
+    "io_type_104": "104.Merge Outbound",
+    "io_type_107": "107.Cycle Count Outbound",
+    "io_type_110": "110.Empty Pallet Outbound",
+    "loc_status_code": "Location Status Code",
+    "loc_status_desc": "Location Status Description",
+    "location_status": "Location Status",
+    "loc_status_D": "D.Empty Bin/Pallet",
+    "loc_status_F": "F.In Stock",
+    "loc_status_G": "G.Aisle",
+    "loc_status_O": "O.Empty Location",
+    "loc_status_P": "P.Picking/Counting/Merging Outbound",
+    "loc_status_Q": "Q.Picking/Counting/Merging Re-inbound",
+    "loc_status_R": "R.Outbound Reserved",
+    "loc_status_S": "S.Inbound Reserved",
+    "loc_status_X": "X.Disabled",
+    "loc_status_Y": "Y.Merged",
+    "parent_menu": "Parent Menu",
+    "category": "Category",
+    "please_input_net_weight_box": "Please input net weight/box",
+    "please_input_gross_weight_box": "Please input gross weight/box",
+    "please_input_remark": "Please input remark",
+    "please_select_type": "Please Select Type",
+    "other": "Other",
+    "responsible_person": "Owner",
+    "please_enter_responsible_person": "Please enter Owner",
+    "classification_name": "Category Name",
+    "please_enter_classification_name": "Please enter Category Name",
+    "sort": "Sort",
+    "please_enter_sort": "Please enter sort",
+    "memo": "Memo",
+    "please_enter_memo": "Please enter memo",
+    "type": "Type",
+    "name": "Name",
+    "image": "Image",
+    "confirm_delete_selected_data": "Are you sure you want to delete the selected data?",
+    "extract_item": "Extract Item",
+    "extract_inventory": "Extract Inventory",
+    "check_station": "Check Station:",
+    "please_select_station": "Please select station",
+    "check_outbound": "Check Outbound",
+    "please_add_check_inventory_first": "Please add check inventory first",
+    "requesting": "Requesting...",
+    "inbound_station": "Inbound Station:",
+    "please_select_station": "Please Select Station",
+    "start_inbound": "Start Inbound",
+    "remove": "Remove",
+    "quantity_required": "Quantity (Required)",
+    "batch_optional": "Batch (Optional)",
+    "operation": "Operation",
+    "please_enter_number": "Please enter a number",
+    "quantity_must_be_greater_than_zero": "Quantity must be greater than zero",
+    "please_extract_item_first": "Please extract item first",
+    "please_select_inbound_station": "Please select inbound station",
+    "inbound_started_success_target_loc": "Inbound started successfully, target location: ",
+    "requesting": "Requesting...",
+    "select_item": "Select Item",
+    "search_bar": "Search Bar",
+    "confirm_extract": "Extract",
+    "please_input_search_condition": "Please input search condition",
+    "empty_pallet_inbound_station": "Empty Pallet Inbound Station",
+    "empty_pallet_outbound_station": "Empty Pallet Outbound Station:",
+    "please_select_outbound_station": "Please select outbound station",
+    "start_outbound": "Start Outbound",
+    "extract": "Extract",
+    "extract_inventory_item": "Extract Inventory Item",
+    "target_empty_location": "Target Empty Location",
+    "location_transfer": "Location Transfer",
+    "please_enter_source_location": "Please enter source location",
+    "please_select_target_location": "Please select target location",
+    "please_enter_and_select": "Please enter and select",
+    "please_retrieve_location_first": "Please retrieve location first",
+    "current_retrieve_location": "Current location",
+    "add_inventory": "Add Inventory",
+    "adjust_inventory": "Adjust Inventory",
+    "actual_quantity": "Actual Qty",
+    "batch_edit": "Batch (Edit)",
+    "please_add_detail_first": "Please add detail first",
+    "quantity_cannot_be_less_than_zero": "Quantity cannot be less than zero",
+    "confirm_adjust_location_detail": "Are you sure to adjust details for location?",
+    "please_enter_valid_location_no": "Please enter valid location no",
+    "outbound_station": "Outbound Station:",
+    "outbound_quantity": "Outbound Qty",
+    "inventory_quantity": "Inventory Qty",
+    "outbound_qty_cannot_exceed_inventory_qty": "Outbound qty cannot exceed inventory qty",
+    "please_extract_inventory_item_first": "Please extract inventory item first",
+    "code": { "copy": "Copy Code", "copied": "Copied", "copyError": "Copy Failed", "maximize": "Maximize", "restore": "Restore", "preview": "Preview" },
+    "colorpicker": { "clear": "Clear", "confirm": "OK" },
+    "dropdown": { "noData": "No Data" },
+    "flow": { "loadMore": "Load More", "noMore": "No More" },
+    "transfer": { "noData": "No Data", "noMatch": "No Match", "title": ["List 1", "List 2"], "searchPlaceholder": "Search" },
+    "tree": { "defaultNodeName": "Unnamed", "noData": "No Data", "deleteNodePrompt": "Delete node \"{name}\"?" },
+    "upload": { "fileType": { "file": "File", "image": "Image", "video": "Video", "audio": "Audio" }, "validateMessages": { "fileExtensionError": "{fileType} format not supported", "filesOverLengthLimit": "Max {length} files", "currentFilesLength": "Selected {length} files", "fileOverSizeLimit": "Max size {size}" }, "chooseText": "{length} files" },
+    "util": { "timeAgo": { "days": "{days} days ago", "hours": "{hours} hours ago", "minutes": "{minutes} mins ago", "future": "Future", "justNow": "Just now" }, "toDateString": { "meridiem": "AM/PM" } }
+}
\ No newline at end of file
diff --git a/src/main/webapp/static/i18n/en/date.json b/src/main/webapp/static/i18n/en/date.json
new file mode 100644
index 0000000..f028004
--- /dev/null
+++ b/src/main/webapp/static/i18n/en/date.json
@@ -0,0 +1,16 @@
+{
+  "months": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+  "weeks": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+  "time": ["Hr", "Min", "Sec"],
+  "literal": { "year": "Year" },
+  "selectDate": "Select Date",
+  "selectTime": "Select Time",
+  "startTime": "Start Time",
+  "endTime": "End Time",
+  "tools": { "confirm": "OK", "clear": "Clear", "now": "Now", "reset": "Reset" },
+  "rangeOrderPrompt": "End time cannot be earlier than start time",
+  "invalidDatePrompt": "Invalid date or time",
+  "formatErrorPrompt": "Date format error, must follow: {format}",
+  "autoResetPrompt": "Auto reset",
+  "preview": "Preview"
+}
\ No newline at end of file
diff --git a/src/main/webapp/static/i18n/en/form.json b/src/main/webapp/static/i18n/en/form.json
new file mode 100644
index 0000000..6babb05
--- /dev/null
+++ b/src/main/webapp/static/i18n/en/form.json
@@ -0,0 +1,5 @@
+{
+  "select": { "noData": "No Data", "noMatch": "No Match", "placeholder": "Select" },
+  "validateMessages": { "required": "Required", "phone": "Invalid Phone", "email": "Invalid Email", "url": "Invalid URL", "number": "Numbers Only", "date": "Invalid Date", "identity": "Invalid ID" },
+  "verifyErrorPromptTitle": "Prompt"
+}
\ No newline at end of file
diff --git a/src/main/webapp/static/i18n/en/layer.json b/src/main/webapp/static/i18n/en/layer.json
new file mode 100644
index 0000000..d3fcce2
--- /dev/null
+++ b/src/main/webapp/static/i18n/en/layer.json
@@ -0,0 +1,5 @@
+{
+  "confirm": "OK", "cancel": "Cancel", "defaultTitle": "Info",
+  "prompt": { "InputLengthPrompt": "Max {length} chars" },
+  "photos": { "noData": "No photos", "tools": { "rotate": "Rotate", "scaleX": "Flip H", "zoomIn": "Zoom In", "zoomOut": "Zoom Out", "reset": "Reset", "close": "Close" }, "viewPicture": "View Original", "urlError": { "prompt": "Image error, continue?", "confirm": "Next", "cancel": "Exit" } }
+}
\ No newline at end of file
diff --git a/src/main/webapp/static/i18n/en/table.json b/src/main/webapp/static/i18n/en/table.json
new file mode 100644
index 0000000..abb6e3d
--- /dev/null
+++ b/src/main/webapp/static/i18n/en/table.json
@@ -0,0 +1,15 @@
+{
+  "sort": { "asc": "Ascending", "desc": "Descending" },
+  "noData": "No Data",
+  "tools": {
+    "filter": { "title": "Filter Columns" },
+    "export": { "title": "Export", "noDataPrompt": "No data", "compatPrompt": "IE not supported", "csvText": "Export CSV" },
+    "print": { "title": "Print", "noDataPrompt": "No data" }
+  },
+  "dataFormatError": "Data format error",
+  "xhrError": "Request error: {msg}",
+  "laypage": {
+     "prev": "Prev", "next": "Next", "first": "First", "last": "Last",
+     "total": "Total {total}", "pagesize": "/page", "goto": "Go to", "page": "Page", "confirm": "OK"
+  }
+}
\ No newline at end of file

--
Gitblit v1.9.1