Browse Source

Added zh-TW translation for file explorer

TC pushbot 5 4 years ago
parent
commit
cc0935fe60

+ 138 - 113
web/SystemAO/file_system/file_explorer.html

@@ -11,6 +11,7 @@
         <script type="text/javascript" src="../../script/ao_module.js"></script>
         <script type="text/javascript" src="../../script/forge-sha256.min.js"></script>
         <script type="text/javascript" src="../../script/qrcode.min.js"></script>
+        <script type="text/javascript" src="../../script/applocale.js"></script>
         <script>
              window.mobilecheck = function() {
                 var check = false;
@@ -597,7 +598,7 @@
                 color: #69aaff !important;
             }
 
-            .dropdown.inverted{
+            .dropdown.inverted:not(.icon){
                 background-color: #17161f !important;
             }
 
@@ -649,7 +650,7 @@
             <button class="ts icon tiny button standard whiteTheme singleObjectOnly" title="Share File" onclick="shareFile();"><i class="share alternate icon"></i></button>
             <button class="ts labeled icon tiny button standard whiteTheme" style="width:154px;"  title="Download" onclick="downloadFile();">
                 <i class="download icon"></i>
-                Download
+                <span locale="menu/button/download">Download</span>
             </button>
 
              <!-- File Edit Operations -->
@@ -687,12 +688,12 @@
                 </div>
                 <div class="rightAlign">
                     <select id="sortingMethodSelector" title="Sorting Method" class="ts basic borderless mini dropdown" onchange="updateSortingMethods();" autocomplete="off">
-                        <option value="default">Ascending</option>
-                        <option value="reverse">Descending</option>
-                        <option value="smallToLarge">Smallest</option>
-                        <option value="largeToSmall"> Largest</option>
-                        <option value="mostRecent">Most Recent</option>
-                        <option value="leastRecent">Least Recent</option>
+                        <option value="default" locale="menu/sort/asc">Ascending</option>
+                        <option value="reverse" locale="menu/sort/desc">Descending</option>
+                        <option value="smallToLarge" locale="menu/sort/small">Smallest</option>
+                        <option value="largeToSmall" locale="menu/sort/large"> Largest</option>
+                        <option value="mostRecent" locale="menu/sort/mostrecent">Most Recent</option>
+                        <option value="leastRecent" locale="menu/sort/leastrecent">Least Recent</option>
                     </select>
                     <button id="searhbtn" class="ts icon tiny button standard whiteTheme"  title="Search" onclick="toggleSearch();"><i class="search icon"></i></button>
                     <button class="ts icon tiny button standard whiteTheme videmode" mode="grid" title="Block View" onclick="changeViewMode(this);"><i class="block layout icon"></i></button>
@@ -727,7 +728,7 @@
                 <div class="ts list">
                     <details class="ts accordion fluid whiteTheme" open>
                         <summary>
-                            <i class="dropdown icon"></i> User
+                            <i class="dropdown icon"></i> <span locale="sidebar/vroot/user">User</span>
                         </summary>
                         <div id="userroot" class="ts list" style="padding-top:0px !important;">
                             <div class="dir item whiteTheme"><i class="loading circle notched rightmargin icon"></i> Initiating</div>
@@ -735,7 +736,7 @@
                     </details>
                     <details class="ts accordion fluid whiteTheme" open>
                         <summary>
-                            <i class="dropdown icon"></i> Storage
+                            <i class="dropdown icon"></i> <span locale="sidebar/vroot/fsh">Storage</span>
                         </summary>
                         <div id="storageroot" class="ts list" style="padding-top:0px !important;">
                             <div class="dir item whiteTheme"><i class="loading circle notched rightmargin icon"></i> Initiating</div>
@@ -774,44 +775,44 @@
         <!-- Overwrite Selection Box-->
         <div id="overwriteModeSelection" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="paste icon"></i> Replace, Keep or Skip Files
+                <i class="paste icon"></i> <span locale="opr/overwrite/title">Replace, Keep or Skip Files</span> 
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <small style="font-size:80%;">Copying <span class="owm-fc"></span> files from <span class="owm-srcdir"></span> to <span class="owm-destdir"></span>.</small>
-                <p>The destination has <span class="owm-fc"></span> files with the same names.</p>
+                <small style="font-size:80%;"><span locale="opr/overwrite/copying">Copying</span> <span class="owm-fc"></span> <span locale="opr/overwrite/files">files from</span> <span class="owm-srcdir"></span> <span locale="opr/overwrite/to">to</span> <span class="owm-destdir"></span></small>
+                <p><span locale="opr/overwrite/dest">The destination has </span><span class="owm-fc"></span> <span locale="opr/overwrite/samename">files with the same names.</span></p>
 
                 <div class="popupbuttons whiteTheme allowHover primary" onclick="changeOverwriteRule(0,true);">
-                    <i class="checkmark icon"></i> Replace the files in the destination
+                    <i class="checkmark icon"></i> <span locale="opr/overwrite/replace">Replace the files in the destination</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="changeOverwriteRule(1,true);">
-                    <i class="reply icon"></i> Skip these files
+                    <i class="reply icon"></i> <span locale="opr/overwrite/skip">Skip these files</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="changeOverwriteRule(2,true);">
-                    <i class="undo icon"></i> Rename and keep the files
+                    <i class="undo icon"></i> <span locale="opr/overwrite/keep">Rename and keep the files</span>
                 </div>
             </div>
         </div>
         <!-- Force delete confirmation box -->
         <div id="forceDeleteConfirmBox" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="trash icon"></i> Permanently Remove Files
+                <i class="trash icon"></i> <span locale="opr/per-remove/title">Permanently Remove Files</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <p>Are you sure you want to remove these files <u>permanently?</u><br>This action is <u>irreversible</u>.</p>
+                <p locale="opr/per-remove/questions">Are you sure you want to remove these files <u>permanently?</u><br>This action is <u>irreversible</u>.</p>
                 <div class="ts list whiteTheme deleteFilelist" style="max-height:350px;overflow-y:auto; ">
 
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" style="background-color: #eb4034 !important;" onclick="forceDelete(true);";>
-                <i class="trash icon"></i> Confirm
+                <i class="trash icon"></i> <span locale="opr/per-remove/confirm">Confirm</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="cancelForceDelete();hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/per-remove/cancel">Cancel</span>
                 </div>
 
             </div>
@@ -820,21 +821,21 @@
         <!-- Delete confirm box -->
         <div id="deleteConfirmBox" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="recycle icon"></i> Move files to Trash Bin
+                <i class="recycle icon"></i> <span locale="opr/remove/title">Move files to Trash Bin</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <p>Are you sure you want to move these files to trash bin?</p>
+                <p locale="opr/remove/question">Are you sure you want to move these files to trash bin?</p>
                 <div class="ts list whiteTheme deleteFilelist" style="max-height:350px;overflow-y:auto; ">
 
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" style="color: #2bbbdf !important;" onclick="deleteFile(true);";>
-                <i class="recycle icon"></i> Move to Trash
+                <i class="recycle icon"></i> <span locale="opr/remove/confirm">Move to Trash</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="cancelDelete();hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/remove/cancel">Cancel</span>
                 </div>
 
             </div>
@@ -843,13 +844,13 @@
         <!-- Rename tool box -->
         <div id="renameBox" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="text cursor icon"></i> Rename Files
+                <i class="text cursor icon"></i> <span locale="opr/rename/title">Rename Files</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <p>Enter the new filename for renaming. </p>
+                <p locale="opr/rename/instruction">Enter the new filename for renaming. </p>
                 <p class="multifileWarning"><i class="notice icon"></i> Other files will be named as file(#)</p>
                 <div class="ts left icon small fluid input" style="margin-bottom:12px;">
                     <input type="text" class="whiteTheme orgfn" placeholder="Original Filename" readonly="true">
@@ -860,10 +861,10 @@
                     <i class="add square icon" style="color:rgb(122, 176, 247)"></i>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover primary"  onclick="confirmRename(true);";>
-                <i class="checkmark icon"></i> OK
+                <i class="checkmark icon"></i> <span locale="opr/rename/ok">OK</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/rename/cancel">Cancel</span>
                 </div>
 
             </div>
@@ -872,27 +873,27 @@
         <!-- New File Dialog-->
         <div id="newFile" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="add icon"></i> New File
+                <i class="add icon"></i> <span locale="opr/newfile/title">New File</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <p>Please select a type of file to be created.</p>
+                <p locale="opr/newfile/instruction">Select a type of file to be created.</p>
                 <div class="ts segmented list whiteTheme newfilelist" style="max-height:18em; overflow-y:scroll">
                     <div class="item newFileFormat" ext="php">No Item</div>
                 </div>
-                <p>Or create an empty file with given filename:</p>
+                <p locale="opr/newfile/newempty">Or create an empty file with given filename:</p>
                 <div class="ts left icon small fluid input" style="margin-bottom:12px;">
                     <input id="createNewFileName" type="text" class="whiteTheme" placeholder="New Filename" onkeydown="handleEnterKeyDown(event, confirmNewFile);">
                     <i class="add square icon" style="color:rgb(122, 176, 247)"></i>
                 </div>
                 <p class="duplicateWarning" style="color:#CE5F58; display:none;"><i class="caution sign icon"></i> The given filename already exist.</p>
                 <div class="popupbuttons whiteTheme allowHover primary"  onclick="confirmNewFile();";>
-                    <i class="add icon"></i> Create
+                    <i class="add icon"></i> <span locale="opr/newfile/create">Create</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/newfile/cancel">Cancel</span>
                 </div>
             </div>
         </div>
@@ -900,23 +901,23 @@
         <!-- New Folder Dialog-->
         <div id="newFolder" class="popup whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="folder icon"></i> New Folder
+                <i class="folder icon"></i> <span locale="opr/newfolder/title">New Folder</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-                <p>Please enter the new folder name to be created.</p>
+                <p locale="opr/newfolder/desc">Enter the new folder name to be created.</p>
                 <div class="ts left icon small fluid input" style="margin-bottom:12px;">
                     <input id="createNewFolder" type="text" class="whiteTheme" placeholder="New Folder Name" onkeydown="handleEnterKeyDown(event, function(){newFolder(true);});">
                     <i class="add square icon" style="color:rgb(122, 176, 247)"></i>
                 </div>
-                <p class="duplicateWarning" style="color:#CE5F58; display:none;"><i class="caution sign icon"></i> The given folder already exist.</p>
+                <p class="duplicateWarning" style="color:#CE5F58; display:none;"><i class="caution sign icon"></i> <span locale="opr/newfolder/alreadyExists">The given folder already exist.</span></p>
                 <div class="popupbuttons whiteTheme allowHover primary"  onclick="newFolder(true);";>
-                    <i class="add icon"></i> Create
+                    <i class="add icon"></i> <span locale="opr/newfolder/create">Create</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/newfolder/cancel">Cancel</span>
                 </div>
             </div>
         </div>
@@ -924,7 +925,7 @@
         <!-- Share File Dialog-->
         <div id="shareFile" class="popup wide whiteTheme" style="display:none;">
             <div class="popupheader whiteTheme">
-                <i class="external icon"></i> Share File
+                <i class="external icon"></i> <span locale="opr/share/title">Share File</span>
                 <div class="popupcloser" onclick="hideAllPopupWindows();">
                     <i class="remove icon"></i>
                 </div>
@@ -941,20 +942,20 @@
                     </div>
                     <div class="eight wide column" style="padding-left: 12px;">
                         <div class="ts header whiteTheme">
-                            Share Settings
-                            <div class="sub header whiteTheme">Change who can see this file</div>
+                            <span locale="opr/share/settings">Share Settings</span>
+                            <div class="sub header whiteTheme" locale="opr/share/setdesc">Change who can see this file</div>
                         </div>
                         <div id="shareSettingForm" class="ts form">
                             <div class="field">
-                                <label><p class="whiteTheme">Visable options:</p></label>
+                                <label><p class="whiteTheme" locale="opr/share/visableoption">Visable options:</p></label>
                                 <div class="ts checkboxes">
                                     <div class="ts radio checkbox">
                                         <input id="anyone" type="radio" class="shareoption" name="shareopt" value="anyone" checked="true">
                                         <label for="anyone">
                                             <div class="ts header">
                                                 <div class="content whiteTheme">
-                                                    <i class="globe icon"></i> Anyone with the link
-                                                    <div class="sub header whiteTheme">Anyone who has the link can access this file</div>
+                                                    <i class="globe icon"></i> <span locale= "opr/share/anyone">Anyone with the link</span>
+                                                    <div class="sub header whiteTheme" locale="opr/share/anyonedesc">Anyone who has the link can access this file</div>
                                                 </div>
                                             </div>
                                         </label>
@@ -964,8 +965,8 @@
                                         <label for="signedin">
                                             <div class="ts header">
                                                 <div class="content whiteTheme">
-                                                    <i class="user circle outline icon"></i> Anyone signed in
-                                                    <div class="sub header whiteTheme">Anyone who has signed in can access this file</div>
+                                                    <i class="user circle outline icon"></i> <span locale="opr/share/signedin">Anyone signed in</span>
+                                                    <div class="sub header whiteTheme" locale="opr/share/signedindesc">Anyone who has signed in can access this file</div>
                                                 </div>
                                             </div>
                                         </label>
@@ -975,14 +976,14 @@
                                         <label for="samegroup">
                                             <div class="ts header">
                                                 <div class="content whiteTheme">
-                                                    <i class="users icon"></i> Users in the same group
-                                                    <div class="sub header whiteTheme">Anyone who is in the same group as you do</div>
+                                                    <i class="users icon"></i> <span locale="opr/share/samegroup">Users in the same group</span>
+                                                    <div class="sub header whiteTheme" locale="opr/share/samegroupdesc">Anyone who is in the same group as you do</div>
                                                 </div>
                                             </div>
                                         </label>
                                     </div>
                                     <br>
-                                    <button class="ts small button" onclick="updateShareSettings(this)" style="border: 0px solid transparent;">Update</button>
+                                    <button class="ts small button" onclick="updateShareSettings(this)" locale="opr/share/update" style="border: 0px solid transparent;">Update</button>
                                 </div>
                             </div>
                         </div>
@@ -991,10 +992,10 @@
                 
                 <div class="ts divider"></div>
                 <div id="sharingRemoveBtn" class="popupbuttons negative whiteTheme allowHover" onclick="removeSharing()">
-                    <i class="remove icon"></i> Remove Sharing
+                    <i class="remove icon"></i> <span locale="opr/share/remove">Remove Sharing</span>
                 </div> 
                 <div class="popupbuttons whiteTheme allowHover" onclick="hideShare()">
-                    <i class="checkmark icon"></i> OK
+                    <i class="checkmark icon"></i> <span locale="opr/share/ok">OK</span>
                 </div> 
             </div>
         </div>
@@ -1008,25 +1009,25 @@
                 </div>
             </div>
             <div class="popupcontent" style="padding:12px;">
-               <p>Select a module from the list below:</p>
+               <p locale="opr/openwith/desc">Select a module from the list below:</p>
                 <div id="openWithModuleList" class="ts segment whiteTheme" style="padding:0px;">
                     <div class="item selectable">
                         <div class="content" style="padding-left:12px;">
-                            <div class="header">Loading...</div>
+                            <div class="header" locale="opr/openwith/loading">Loading...</div>
                         </div>
                     </div>
                 </div>
                 <div class="openWithModule popupbuttons whiteTheme allowHover primary" onclick="openWithSelectedModule(this);";>
-                    <i class="external icon"></i> Open with Selected Module
+                    <i class="external icon"></i> <span locale="opr/openwith/openWithWebApp">Open with Selected Module</span>
                 </div> 
                 <div class="openWithModule popupbuttons whiteTheme allowHover" onclick="openFileWithModuleInNewTab(this);">
-                    <i class="add icon"></i> Open in new tab
+                    <i class="add icon"></i> <span locale="opr/openwith/openWithWebAppInNewWindow">Open in new tab</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover vdonly" onclick="openRawFileInFloatWindow(this);">
-                    <i class="window restore outline icon"></i> Open File directly in floatWindow
+                    <i class="window restore outline icon"></i> <span locale="opr/openwith/openInNewWindow">Open File directly in floatWindow</span>
                 </div>
                 <div class="popupbuttons whiteTheme allowHover" onclick="hideAllPopupWindows();">
-                    <i class="remove icon"></i> Cancel
+                    <i class="remove icon"></i> <span locale="opr/openwith/cancel">Cancel</span>
                 </div>
             </div>
         </div>
@@ -1034,87 +1035,87 @@
         <!-- Context Menu -->
         <div id="contextmenu" class="ts small contextmenu visible whiteTheme" style="min-width:250px;">
             <div class="item" onclick="openViaButton();">
-                <i class="folder open icon"></i>  Open
+                <i class="folder open icon"></i> <span locale="contextmenu/open">Open</span>
             </div>
             <div class="item fileonly" onclick="openWith();">
-                <i class="external icon"></i> Open With
+                <i class="external icon"></i> <span locale="contextmenu/openWith">Open With</span>
             </div>
             <div class="item folderonly" onclick="openSelectedFolderInNewWindow();">
-                <i class="external icon"></i> Open In New Window
+                <i class="external icon"></i> <span locale="contextmenu/openNewWindow">Open In New Window</span>
             </div>
             <!-- This is the vroot alternative new windows-->
             <div class="item vrootonly" onclick="openSelectedVroot();">
-                <i class="external icon"></i> Open In New Window
+                <i class="external icon"></i> <span locale="contextmenu/openNewWindowVroot">Open In New Window</span>
             </div>
             <div class="item shareonly" onclick="openFileLocation();">
-                <i class="folder outline icon"></i> Open File Location
+                <i class="folder outline icon"></i> <span locale="contextmenu/openFileLocation">Open File Location</span>
             </div>
             <div class="item singleObjectOnlyHide" onclick="shareFile();">
-                <i class="share alternate icon"></i> Share
+                <i class="share alternate icon"></i> <span locale="contextmenu/Share">Share</span>
             </div>
             <div class="item mobileonly" onclick="toggleCtrl();">
-                <i class="mouse pointer icon"></i> Multi-select
+                <i class="mouse pointer icon"></i> <span locale="contextmenu/MuitSelect">Multi-select</span>
             </div>
             <div class="item" onclick="copy();">
-                <i class="copy icon"></i> Copy
+                <i class="copy icon"></i> <span locale="contextmenu/copy">Copy</span>
                 <span class="description">Ctrl + C</span>
             </div>
             <div class="item allowNoSelection" onclick="paste();">
-                <i class="paste icon"></i> Paste
+                <i class="paste icon"></i> <span locale="contextmenu/paste">Paste</span>
                 <span class="description">Ctrl + V</span>
             </div>
             <div class="item" onclick="cut();">
-                <i class="cut icon"></i> Cut
+                <i class="cut icon"></i> <span locale="contextmenu/cut">Cut</span>
                 <span class="description">Ctrl + X</span>
             </div>
             <div class="divider vroothide noSelectionOnly"></div>
             <div class="item noSelectionOnly" onclick="newfile();">
-                <i class="file outline icon"></i>  New File
+                <i class="file outline icon"></i>  <span locale="contextmenu/newFile">New File</span>
             </div>
             <div class="item noSelectionOnly" onclick="newFolder();">
-                <i class="folder outline icon"></i> New Folder
+                <i class="folder outline icon"></i> <span locale="contextmenu/newFolder">New Folder</span>
             </div>
             <div class="divider vroothide"></div>
             <div class="item noSelectionOnly" onclick="upload();">
-                <i class="upload icon"></i>  Upload
+                <i class="upload icon"></i>  <span locale="contextmenu/upload">Upload</span>
             </div>
             <div class="item" onclick="zipFile();">
-                <i class="zip file icon"></i> Create Zip
+                <i class="zip file icon"></i> <span locale="contextmenu/zip">Create Zip</span>
             </div>
             <div class="item" onclick="rename();">
-                <i class="i cursor icon"></i> Rename
+                <i class="i cursor icon"></i> <span locale="contextmenu/rename">Rename</span>
             </div>
             <div class="item" onclick="deleteFile();">
-                <i class="trash icon"></i> Delete
+                <i class="trash icon"></i> <span locale="contextmenu/delete">Delete</span>
             </div>
             <div class="item backuponly" onclick="openBackupManager();">
-                <i class="block layout icon"></i> Backup & Restore
+                <i class="block layout icon"></i> <span locale="contextmenu/backup">Backup & Restore</span>
             </div>
             <div class="divider vroothide"></div>
             <div class="item noSelectionOnly" onclick="refreshList();">
-                <i class="refresh icon"></i> Refresh
+                <i class="refresh icon"></i> <span locale="contextmenu/refresh">Refresh</span>
             </div>
             <div class="item" onclick="downloadFile();">
-                <i class="download icon"></i> Download
+                <i class="download icon"></i> <span locale="contextmenu/download">Download</span>
             </div>
             <div class="item" onclick="showFileProperties();">
-                <i class="notice icon"></i> Properties
+                <i class="notice icon"></i> <span locale="contextmenu/properties">Properties</span>
             </div>
             <!-- This properties shows the currentDirectory properties instead of the selected file properties-->
             <div class="item noSelectionOnly" onclick="showCurrentDirectoryProperties();">
-                <i class="notice icon"></i> Properties
+                <i class="notice icon"></i> <span locale="contextmenu/properties">Properties</span>
             </div>
             <!-- This properties show the vroot properties -->
              <!-- This properties shows the currentDirectory properties instead of the selected file properties-->
              <div class="item vrootonly" onclick="showVrootProperties();">
-                <i class="notice icon"></i> Properties
+                <i class="notice icon"></i> <span locale="contextmenu/properties">Properties</span>
             </div>
         </div>
 
         <!-- Upload Progress Bars-->
         <div id="uploadTab" class="ts segment whiteTheme" style="display:none;">
             <div class="statusBar whiteTheme">
-                <i class="upload icon"></i><span id="uploadCount">0</span> Files / <i class="wait icon"></i> <span id="waitingCount">0</span> Files
+                <i class="upload icon"></i><span id="uploadCount">0</span> <span locale="upload/count/uploading">Files</span> / <i class="wait icon"></i> <span id="waitingCount">0</span> <span locale="upload/count/pending">Files</span>
                 <div class="hideUploadButton" onclick="toggleUploadList();">
                     <i class="caret down icon"></i>
                 </div>
@@ -1123,11 +1124,6 @@
               
             </div>
             <br>
-            <!-- 
-            <div class="clearallButton">
-                <a onclick="clearAllUploadTask();">Clear All</a>
-            </div>
-            -->
         </div>
 
            
@@ -1187,9 +1183,26 @@
             let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
 
             //Intiiation functions
-            initRootDirs();
-            initSystemInfo();
-            initUploadMode();
+            if (applocale){
+                //Applocale found. Do localization
+                applocale.init("../locale/file_explorer.json", function(){
+                    applocale.translate();
+                    initRootDirs();
+                    initSystemInfo();
+                    initUploadMode();
+                });
+            }else{
+                //Applocale not found. Is this a trim down version of ArozOS?
+                applocale = {
+                    getString: function(key, original){
+                        return original;
+                    }
+                }
+                initRootDirs();
+                initSystemInfo();
+                initUploadMode();
+            }
+           
 
             if (isMobile){
                 //Mobile css adjustment
@@ -1331,8 +1344,9 @@
                             var thisRootObject = data[i];
                             if (thisRootObject.IsDir == true && !(thisRootObject.Filename == ".cache" || thisRootObject.Filename == ".trash")){
                                 //Files will not be listed in the root directory list
-                                var icon = getUserRootIcons(thisRootObject.Filename);
-                                var displayName = thisRootObject.Filename;
+                                var specifcRootInfo = getUserRootIcons(thisRootObject.Filename);
+                                var icon = specifcRootInfo[0];
+                                var displayName = specifcRootInfo[1];
                                 var vpath = thisRootObject.Filepath;
                                 $("#userroot").append(`<div class="dir item ${currentTheme}" filepath="${vpath}" type="folder" onclick="openthis(this);"><i class="${icon} rightmargin icon"></i> ${displayName}</div>`);
                             }
@@ -1385,29 +1399,40 @@
 
             function getUserRootIcons(foldername){
                 var icon = "folder open";
+                var name = foldername;
                 foldername = foldername.toLowerCase();
                 if (foldername == "desktop"){
                     icon = "computer";
+                    name = applocale.getString("sidebar/vroot/desktop", name);
                 }else if (foldername == "document"){
                     icon = "file text outline";
+                    name = applocale.getString("sidebar/vroot/document", name);
                 }else if (foldername == "music" || foldername == "audio"){
                     icon = "music";
+                    name = applocale.getString("sidebar/vroot/music", name);
                 }else if (foldername == "photo" || foldername == "picture"){
                     icon = "image";
+                    name = applocale.getString("sidebar/vroot/photo", name);
                 }else if (foldername == "video" || foldername == "film"){
                     icon = "video";
+                    name = applocale.getString("sidebar/vroot/video", name);
                 }else if (foldername == "trash" || foldername == "bin" || foldername == "rubbish"){
                     icon = "trash"
+                    name = applocale.getString("sidebar/vroot/trash", name);
                 }else if (foldername == "download"){
                     icon = "download"
+                    name = applocale.getString("sidebar/vroot/download", name);
                 }else if (foldername == "www" || foldername == "web" || foldername == "mysite"){
                     icon = "globe"
+                    name = applocale.getString("sidebar/vroot/web", name);
                 }else if (foldername == "model"){
                     icon = "cube"
+                    name = applocale.getString("sidebar/vroot/model", name);
                 }else if (foldername == "appdata"){
                     icon = "code"
+                    name = applocale.getString("sidebar/vroot/appdata", name);
                 }
-                return icon;
+                return [icon, name];
             }
 
             // ============================== FOLDER LISTING FUNCTIONS ====================
@@ -2417,7 +2442,7 @@
                 var oldName = $("#renameBox").find(".orgfn").val();
                 var newName = $("#renameBox").find(".newfn").val();
                 if (newName == oldName){
-                    msgbox("remove","New filename is identical to the original filename.")
+                    msgbox("remove",applocale.getString("message/newFilenameIdentical", "New filename is identical to the original filename."));
                     $("#renameBox").fadeOut(100);
                     $(".popupWrapper").fadeOut(100);
                     return;
@@ -2464,7 +2489,7 @@
                                 msgbox("remove",data.error);
                             }else{
                                 refreshList();
-                                msgbox("checkmark","Rename suceed");
+                                msgbox("checkmark",applocale.getString("message/rename/success", "Rename suceed"));
                             }
                             $("#renameBox").fadeOut(100);
                             $(".popupWrapper").fadeOut(100);
@@ -2517,7 +2542,7 @@
                     localStorage.setItem("ao/file_system/clipboard",JSON.stringify(clipboard));
                     localStorage.setItem("ao/file_system/cutmode","false");
                 }
-                msgbox("copy",clipboard.length + " objects copied.")
+                msgbox("copy",clipboard.length + applocale.getString("message/copy/success", " objects copied."))
             }
 
             function cut(){
@@ -2534,7 +2559,7 @@
                     localStorage.setItem("ao/file_system/clipboard",JSON.stringify(clipboard));
                     localStorage.setItem("ao/file_system/cutmode","true");
                 }
-                msgbox("cut",clipboard.length + " objects ready to be moved.")
+                msgbox("cut",clipboard.length + applocale.getString("message/move/success", " objects ready to be moved."))
             }
 
             function paste(redirectPasteTarget="", nocheck=false){
@@ -2558,7 +2583,7 @@
                 }
                 if (fileList.length == 0){
                     //There are nothing to paste
-                    msgbox("question","There are nothing to paste.")
+                    msgbox("question",applocale.getString("message/paste/nothing", "There are nothing to paste."))
                     return;
                 }
                 //console.log(fileList,JSON.stringify(fileList));
@@ -2591,7 +2616,7 @@
                                                     msgbox("remove",data.error);
                                                 }else{
                                                     //OK
-                                                    msgbox("checkmark",fileList.length + " objects moved.")
+                                                    msgbox("checkmark",fileList.length + applocale.getString("message/move/success", " objects moved."))
                                                     refreshList();
                                                 }
                                                 hideAllPopupWindows();
@@ -2652,7 +2677,7 @@
                                                     msgbox("remove",data.error);
                                                 }else{
                                                     //OK
-                                                    msgbox("checkmark",fileList.length + " objects copied.")
+                                                    msgbox("checkmark",fileList.length + applocale.getString("message/copy/success", " objects copied."))
                                                     refreshList();
                                                 }
                                                 hideAllPopupWindows();
@@ -2749,7 +2774,7 @@
                                     msgbox("caution",data.error);
                                 }else{
                                     refreshList();
-                                    msgbox("checkmark",fdlistLength + " objects removed.")
+                                    msgbox("checkmark",fdlistLength + applocale.getString("message/remove/success", " objects removed."))
                                 }
                                 hideAllPopupWindows();
                             }
@@ -2793,7 +2818,7 @@
                                     msgbox("caution",data.error);
                                 }else{
                                     refreshList();
-                                    msgbox("checkmark",fdlistLength + " objects moved to trash bin.")
+                                    msgbox("checkmark",fdlistLength + applocale.getString("message/recycle/success", " objects moved to trash bin."))
                                 }
 
                                 if (currentPath == "user:/"){
@@ -2826,7 +2851,7 @@
                 input.multiple = true;
                 input.onchange = e => { 
                     var files = e.target.files; 
-                    msgbox("upload","Upload Started");
+                    msgbox("upload",applocale.getString("message/upload/started", "Upload Started"));
                     for (var i = 0; i < files.length; i++){
                         uploadFile(files[i]);
                     }
@@ -3062,7 +3087,7 @@
                         error: function(){
                             targetTaskDisplayObject.find(".progress").removeClass("preparing").removeClass("primary").addClass("negative");
                             targetTaskDisplayObject.find(".bar").css("width", "100%");
-                            msgbox("remove","Zipping failed due to unknown reason");
+                            msgbox("remove",applocale.getString("message/zip/fail", "Zipping failed due to unknown reason"));
 
                             setTimeout(function(){
                                 if ($(".uploadTask").length == 0){
@@ -3187,7 +3212,7 @@
                                 if (data.error !== undefined){
                                     msgbox("remove", data.error);
                                 }else{
-                                    msgbox("checkmark","New folder created.");
+                                    msgbox("checkmark",applocale.getString("message/newfolder/success", "New folder created."));
                                     refreshList();
                                 }
                                 $("#newFolder").fadeOut('fast');
@@ -3226,7 +3251,7 @@
                             if (data.error !== undefined){
                                 msgbox("remove",data.error);
                             }else{
-                                msgbox("checkmark",filename + " created.");
+                                msgbox("checkmark",filename + applocale.getString("message/newItem/success", " created."));
                                 refreshList();
                             }
                         }
@@ -3254,7 +3279,7 @@
             //OpenWith dialog
             function openWith(){
                 if ($(".selected.fileObject").length == 0){
-                    msgbox("question","No file selected");
+                    msgbox("question",applocale.getString("message/nofileSelected", "No file selected"));
                     return;
                 }
                 //Get a list of modules and append it into the selection list
@@ -3335,7 +3360,7 @@
                     //Launch with default mode
 
                 }else{
-                    msgbox("remove","This module has no endpoint for opening a file.");
+                    msgbox("remove",applocale.getString("message/moduleNotSupport", "This module has no endpoint for opening a file."));
                     return;
                 }   
 
@@ -4168,7 +4193,7 @@
                 let files = dt.files
                 if (files.length > 0){
                     //Upload file via dragdrop
-                    msgbox("upload","Upload Started");
+                    msgbox("upload",applocale.getString("message/upload/started", "Upload Started"));
                     let items = event.dataTransfer.items;
                     for (let i=0; i<items.length; i++) {
                         let item = items[i].webkitGetAsEntry();
@@ -4211,7 +4236,7 @@
                                 firstFileDirname = firstFileDirname.join("/");
                                 if (currentDirname == firstFileDirname){
                                     //Drag start and drop location are the same directory
-                                    msgbox("remove","Source and destination file names are the same")
+                                    msgbox("remove",applocale.getString("message/destIdentical", "Source and destination file names are the same"));
                                     return;
                                 }
 
@@ -4248,7 +4273,7 @@
 
                         }catch(ex){
                             console.log(ex);
-                            msgbox("remove","File drop failed. Unable to decode filelist.");
+                            msgbox("remove",applocale.getString("message/decodeFilelistFail", "File drop failed. Unable to decode filelist."));
                         }
                     }
                     
@@ -4729,7 +4754,7 @@
                         }, 100)
                         
                     }else if (xhr.readyState == 4 && xhr.status != 200) {
-                        msgbox("remove","File too big or the target disk is fulled");
+                        msgbox("remove",applocale.getString( "message/uploadFailed", "File too big or the target disk is fulled"));
                         console.log(xhr);
                         $(".uploadTask").each(function(){
                             if ($(this).attr("taskID") == taskUUID){
@@ -4793,9 +4818,9 @@
             $("#folderList").show();
             $("#folderList").html(`<div class="ts basic segment ${currentTheme}">
                 <div class="ts header">
-                    <i class="arrow up icon ${currentTheme}"></i> <span class="${currentTheme}">Type to Start Search</span>
-                    <div class="sub header ${currentTheme}" style="margin-top:12px;">Type something in the search bar to start searching.<br>
-                        Start wildcard matching with "/" (slash) and your wildcard string (e.g. /*.mp3)</div>
+                    <i class="arrow up icon ${currentTheme}"></i> <span class="${currentTheme}">${applocale.getString("func/search/typeToStart", "Type to Start Search")}</span>
+                    <div class="sub header ${currentTheme}" style="margin-top:12px;">${applocale.getString("func/search/tip1", "Type something in the search bar to start searching.")}<br>
+                        ${applocale.getString("func/search/tip2", `Start wildcard matching with "/" (slash) and your wildcard string (e.g. /*.mp3)`)}</div>
                 </div>
             </div>`);
             $("#fileList").hide();

+ 174 - 0
web/SystemAO/locale/file_explorer.json

@@ -0,0 +1,174 @@
+{
+    "author": "tobychui",
+    "version": "1.0",
+    "keys": {
+        "zh-TW": {
+            "strings": {
+                "menu/button/download": "下載所選",
+                "menu/sort/asc": "檔名順序",
+                "menu/sort/desc": "檔名倒序",
+                "menu/sort/small": "小至大",
+                "menu/sort/large": "大至小",
+                "menu/sort/mostrecent": "新到舊",
+                "menu/sort/leastrecent": "舊到新",
+
+                "sidebar/vroot/user":"使用者",
+                "sidebar/vroot/fsh":"虛擬儲存裝置",
+
+                "sidebar/vroot/desktop":"桌面",
+                "sidebar/vroot/document":"文件",
+                "sidebar/vroot/music":"音樂",
+                "sidebar/vroot/photo":"圖片",
+                "sidebar/vroot/video":"影片",
+                "sidebar/vroot/trash":"回收箱",
+                "sidebar/vroot/download":"下載",
+                "sidebar/vroot/web":"網頁",
+                "sidebar/vroot/model":"模型",
+                "sidebar/vroot/appdata":"應用",
+
+                "func/search/typeToStart":"輸入關鍵字以開始搜尋",
+                "func/search/tip1":"在上面的輸入欄位輸入關鍵字,然後按「搜尋」按鈕以開始搜尋",
+                "func/search/tip2":"如你需要輸入萬用字元,請先輸入 / 號,例如: /*.mp3",
+
+                "opr/overwrite/title": "覆寫、保留或是跳過檔案",
+                "opr/overwrite/copying": "正在複制",
+                "opr/overwrite/files": "個檔案。來源:",
+                "opr/overwrite/to": " → 目的地:",
+                "opr/overwrite/dest": "目的地有 ",
+                "opr/overwrite/samename": " 個相同名稱的檔案",
+                "opr/overwrite/replace": "覆寫目的地檔案",
+                "opr/overwrite/skip": "跳過這些檔案",
+                "opr/overwrite/keep": "重新命名並保留目的地檔案",
+
+                "opr/per-remove/title": "永久移除檔案",
+                "opr/per-remove/questions": "確定<u>永久移除</u>以下檔案?<br>移除後檔案將<u>無法覆原</u>",
+                "opr/per-remove/confirm": "確認永久移除所選檔案",
+                "opr/per-remove/cancel": "取消",
+
+                "opr/remove/title": "移動到資源回收箱",
+                "opr/remove/question": "確認移動所選檔案到資源回收箱?",
+                "opr/remove/confirm": "確認",
+                "opr/remove/cancel": "取消",
+
+                "opr/rename/title": "重新命名",
+                "opr/rename/instruction": "請在下方輸入欄輸入新檔案名稱",
+                "opr/rename/ok": "確認",
+                "opr/rename/cancel": "取消",
+
+                "opr/newfile/title": "創建檔案",
+                "opr/newfile/instruction": "選擇一種要新增的檔案格式樣本",
+                "opr/newfile/newempty": "或輸入檔案名稱以新增一個空白檔案",
+                "opr/newfile/create": "新增",
+                "opr/newfile/cancel": "取消",
+
+                "opr/newfolder/title":"創建資料夾",
+                "opr/newfolder/desc":"請在下方輸入欄輸入新資料夾名稱",
+                "opr/newfolder/alreadyExists":"此資料夾已存在",
+                "opr/newfolder/create":"創建",
+                "opr/newfolder/cancel":"取消",
+
+                "opr/share/title":"分享檔案",
+                "opr/share/settings":"分享設定",
+                "opr/share/setdesc":"更改誰能看到此檔案",
+                "opr/share/visableoption":"分享對像:",
+                "opr/share/anyone":"擁有連接的使用者",
+                "opr/share/anyonedesc":"任何擁有分享連接的使用者皆可下載此檔案",
+                "opr/share/signedin":"已登入的使用者",
+                "opr/share/signedindesc":"任何已登入並擁有分享連接的使用者皆可下載此檔案",
+                "opr/share/samegroup":"在同一權限群組內的使用者",
+                "opr/share/samegroupdesc":"任何擁有相同使用者權限的使用者皆可下載此檔案",
+                "opr/share/update":"更新權限",
+                "opr/share/remove":"移除檔案分享",
+                "opr/share/ok":"完成",
+
+                "opr/openwith/title": "使用 … 開啟",
+                "opr/openwith/desc": "選擇一個 WebApp 以開啟此檔案",
+                "opr/openwith/loading": "載入中…",
+                "opr/openwith/openWithWebApp": "使用所選的 WebApp 開啟檔案",
+                "opr/openwith/openWithWebAppInNewWindow": "使用所選的 WebApp 在新視窗開啟",
+                "opr/openwith/openInNewWindow": "直接於新視窗開啟檔案",
+                "opr/openwith/cancel": "取消",
+
+                "contextmenu/open": "開啟",
+                "contextmenu/openWith": "使用 … 開啟",
+                "contextmenu/openNewWindow": "在新視窗開啟",
+                "contextmenu/openNewWindowVroot": "在新視窗開啟",
+                "contextmenu/openFileLocation": "開啟檔案位置",
+                "contextmenu/Share": "分享",
+                "contextmenu/MuitSelect": "切換多選",
+                "contextmenu/copy": "複制",
+                "contextmenu/paste": "貼上",
+                "contextmenu/cut": "剪下",
+                "contextmenu/newFile": "新增檔案",
+                "contextmenu/newFolder": "創建資料夾",
+                "contextmenu/upload": "上載",
+                "contextmenu/zip": "建立壓縮檔",
+                "contextmenu/rename": "重新命名",
+                "contextmenu/delete": "刪除",
+                "contextmenu/backup": "備份及還原",
+                "contextmenu/refresh": "重新整理",
+                "contextmenu/download": "下載",
+                "contextmenu/properties": "內容",
+
+                "upload/count/uploading": " 上載中",
+                "upload/count/pending": " 等待中",
+
+                "message/rename/success": "重新命名成功",
+                "message/copy/success": " 個檔案已準備複制",
+                "message/move/success": " 個檔案已準備移動",
+                "message/paste/nothing": "沒有可貼上的檔案",
+                "message/remove/success": " 個檔案已被成功刪除",
+                "message/recycle/success": " 個檔案已被成功移動到資源回收箱",
+                "message/upload/started": "檔案上載已開始",
+                "message/zip/fail": "檔案壓縮失敗:原因不明",
+                "message/newfolder/success": "新資料夾建立完成",
+                "message/newItem/success": " 建立完成",
+                "message/nofileSelected": "沒有選擇檔案",
+                "message/moduleNotSupport": "此模組無法開啟任何檔案",
+
+                "message/destIdentical": "檔案來原及目的地相同",
+                "message/decodeFilelistFail": "載案置入失敗:無法讀取檔案列表",
+                "message/uploadFailed": "載案上載失敗:檔案太大或目標儲存裝置已滿",
+                "message/newFilenameIdentical": "重新命名失敗:新舊檔案名稱相同"
+            },
+            "titles":{
+                "Back": "上一頁",
+                "Parent Folder": "返回上層目錄",
+                "Open":"開啟",
+                "Open with":"以…開啟",
+                "Share File":"分享所選",
+                "Download":"下載",
+                "Copy":"複制",
+                "Paste":"貼上",
+                "Cut":"剪下",
+                "New File":"新增檔案",
+                "New Folder":"新增資料夾",
+                "Upload":"上載",
+                "Create Zip":"建立壓縮檔",
+                "Rename":"重新命名",
+                "Delete":"刪除",
+                "Refresh":"重新整理",
+                "Home":"根目錄",
+                "File Info":"檔案資訊",
+                "Toggle Folder List":"檢視根目錄列表",
+                "Dark Theme":"切換主題配色",
+                "Edit Path":"編輯路徑",
+                "Sorting Method":"檔案排序",
+                "Search":"搜尋",
+                "Block View":"顯示檔案預覽",
+                "List View":"顯示檔案列表",
+                "Case Sensitive":"區分大小寫",
+                "Clear Search":"清除搜尋結果"
+            },
+            "placeholder": {
+                "New Filename":"在此輸入新檔案名稱",
+                "New Folder Name":"在此輸入新資料夾名稱",
+                "File Search (Start wildcard search with / , e.g. /*.mp3)":"檔案搜尋(如要使用萬用字元,請先輸入 / 號,例如: /*.mp3)"
+                
+            }
+        },
+        "zh-HK": {
+            
+        }
+    }
+}

+ 12 - 0
web/SystemAO/locale/system_settings.json

@@ -0,0 +1,12 @@
+{
+    "author": "tobychui",
+    "version": "1.0",
+    "keys": {
+        "zh-TW": {
+
+        },
+        "zh-HK": {
+            
+        }
+    }
+}

+ 86 - 0
web/script/applocale.js

@@ -0,0 +1,86 @@
+/*
+    Application Locale Module
+    author: tobychui
+
+    This module translate the current web application page 
+    to the desired language specific by the browser.
+
+
+    Example Usage:
+     if (applocale){
+        //Applocale found. Do localization
+        applocale.init("../locale/file_explorer.json", function(){
+            applocale.translate();
+            //Do other init things on the page
+        });
+    }
+*/
+
+
+let applocale = {
+    lang: navigator.language,
+    localeFile: "",
+    localData: {},
+    init: function(localeFile, callback=undefined){
+        applocale.localeFile = localeFile;
+        $.ajax({
+            dataType: "json",
+            url: localeFile,
+            success: function(data){
+                applocale.localData = data;
+                if (callback != undefined){
+                    callback(data);
+                }
+            }
+          });
+    },
+    translate: function(targetLang = ""){
+        var targetLang = targetLang || applocale.lang;
+
+        //Check if the given locale exists
+        if (applocale.localData.keys[targetLang] == undefined){
+            console.log("[Applocale] This language is not supported. Using default")
+            return
+        }
+
+        //Update the page content to fit the localization
+        let hasTitleLocale = (applocale.localData.keys[targetLang].titles !== undefined);
+        let hasStringLocale = (applocale.localData.keys[targetLang].strings !== undefined);
+        let hasPlaceHolderLocale = (applocale.localData.keys[targetLang].placeholder !== undefined);
+        $("*").each(function(){
+            if ($(this).attr("title") != undefined && hasTitleLocale){
+               let targetString = applocale.localData.keys[targetLang].titles[$(this).attr("title")];
+               if (targetString != undefined){
+                    $(this).attr("title", targetString);
+               }
+               
+            }
+
+            if ($(this).attr("locale") != undefined && hasStringLocale){
+                let targetString = applocale.localData.keys[targetLang].strings[$(this).attr("locale")];
+                if (targetString != undefined){
+                    $(this).html(targetString);
+                }
+            }
+
+            if ($(this).attr("placeholder") != undefined && hasPlaceHolderLocale){
+                let targetString = applocale.localData.keys[targetLang].placeholder[$(this).attr("placeholder")];
+                if (targetString != undefined){
+                    $(this).attr("placeholder",targetString);
+                }
+            }
+        })
+   },
+    getString: function(key, original, type="strings"){
+        var targetLang = applocale.lang;
+        if (applocale.localData.keys[targetLang] == undefined){
+            return original;
+        }
+        let targetString = applocale.localData.keys[targetLang].strings[key];
+        if (targetString != undefined){
+            return targetString
+        }else{
+            return original
+        }
+    }
+}