docs(multi lang support): work on getting multi lang support working

This commit is contained in:
2025-09-06 11:58:40 -05:00
parent 1508fb2fa7
commit 945048f43e
39 changed files with 259 additions and 93 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
# ---> Node
app/src/docs
app/src/frontend
lstDocs/i18n
lstWrapper/bin
lstWrapper/obj
lstWrapper/publish

21
.vscode/settings.json vendored
View File

@@ -24,5 +24,24 @@
},
"[handlebars]": {
"editor.formatOnSave": true
}
},
"[go]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "golang.go"
},
"[powershell]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "ms-vscode.powershell" // requires PowerShell extension
},
"[bat]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "foxundermoon.shell-format" // supports .sh, .bat, .cmd
},
"[cmd]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "foxundermoon.shell-format"
},
// Optional: Configure goimports instead of gofmt
"go.formatTool": "goimports"
}

View File

@@ -1,11 +1,11 @@
meta {
name: build app V2
name: version
type: http
seq: 2
}
post {
url: http://localhost:8080/build
get {
url: http://localhost:8080/version
body: none
auth: inherit
}

View File

@@ -15,6 +15,24 @@ func main() {
// POST /build -> run npm build + increment .build
r.POST("/build", func(c *gin.Context) {
host, err := os.Hostname()
if err != nil {
c.JSON(500, gin.H{"error": "Could not retrieve hostname"})
return
}
log.Println(host)
if strings.Contains(host, "VMS") || strings.Contains(host, "vms") {
c.JSON(500, gin.H{"error": "You are not allowed to run the build on a production server"})
return
}
// run the old builder first this will be removed once we switch fully over here and shut down the old version
if err := runNpmV2Build(); err != nil {
c.JSON(500, gin.H{"error": "npm build failed on lstV2", "details": err.Error()})
return
}
// the new builder
if err := runNpmBuild(); err != nil {
c.JSON(500, gin.H{"error": "npm build failed", "details": err.Error()})
return
@@ -59,29 +77,9 @@ func main() {
})
})
r.POST("/buildv2", func(c *gin.Context) {
if err := runNpmV2Build(); err != nil {
c.JSON(500, gin.H{"error": "npm build failed on lstV2", "details": err.Error()})
return
}
buildNum, err := bumpBuild()
if err != nil {
c.JSON(500, gin.H{"error": "failed updating build counter", "details": err.Error()})
return
}
c.JSON(200, gin.H{
"message": "build successful",
"build": buildNum,
})
})
// GET /version -> read current build version
r.GET("/version", func(c *gin.Context) {
data, err := os.ReadFile(".build")
data, err := os.ReadFile("../.build")
if err != nil {
c.JSON(404, gin.H{"error": "no build info"})
return
@@ -91,4 +89,3 @@ func main() {
r.Run(":8080") // serve API
}

5
lang/de.json Normal file
View File

@@ -0,0 +1,5 @@
{
"intro.title": "Einführung",
"intro.heading": "Willkommen zu unserer Dokumentation",
"intro.body": "Dies ist der deutsche Einführungsabsatz."
}

5
lang/en.json Normal file
View File

@@ -0,0 +1,5 @@
{
"intro.title": "Introduction",
"intro.heading": "Welcome to our Docs",
"intro.body": "This is the English introduction paragraph."
}

5
lang/es.json Normal file
View File

@@ -0,0 +1,5 @@
{
"intro.title": "Introducción",
"intro.heading": "Bienvenido a nuestra Documentación",
"intro.body": "Este es el párrafo de introducción en español."
}

View File

@@ -15,28 +15,28 @@ Please note that if you plan to utlize the scanner app you must use IIS to run a
1. Open IIS
2. Expand the plant and select application pools
![](./img/applicationPools.png)
![](/img/install/applicationPools.png)
3. Right click and create application
![](./img/createApplicationPool.png)
![](/img/install/createApplicationPool.png)
4. Name is Logistics Support Tool
- Change .NET CLR verion to not managed
- leave the rest as default
![](./img/pool.png)
![](/img/install/pool.png)
## Create the website
1. Expand the Sites
![](./img/defaultsite.png)
![](/img/install/defaultsite.png)
2. Right click on default site and click "Add Application..."
![](./img/addApplication.png)
![](/img/install/addApplication.png)
3. Fill out the form like below
@@ -48,7 +48,7 @@ Please note that if you plan to utlize the scanner app you must use IIS to run a
E:\LST\lstWrapper
```
![](./img/application.png)
![](/img/install/application.png)
## Making sure websocket is enabled

View File

@@ -1,5 +1,6 @@
---
sidebar_position: 2
id: install
---
# Install Process
@@ -105,7 +106,7 @@ Make sure you have installed both
open the app in vs code
open terminal
![](./install-extras/img/terminal.png)
![](/img/install/terminal.png)
run the install command

View File

@@ -1,5 +1,9 @@
---
sidebar_position: 1
id: intro
title: intro.title
---
---
# Logisitcs Support Tool Intro

View File

@@ -1,5 +1,6 @@
---
sidebar_position: 1
id: ocp
---
# Material Consumption
@@ -22,7 +23,7 @@ here you will be able to see the logs for the last 4 hours to identifty what the
below is an example of missing materials.
![](./img/logs.png)
![](/img/ocp/logs.png)
as you see this lot is missing a lot of items. if the packer keeps pressing the pause button you will see quite a few of these.
@@ -39,16 +40,16 @@ To correct these errors follow each error.
Grab a scanner and scan the Consume non-prepared material
![](./img/consume.png)
![](/img/ocp//consume.png)
next grab the production work order of the lot you will be running the material on.
Then scan the top barcode.
![](./img/workorder.png)
![](/img/ocp//workorder.png)
Lastly scan the cage of preforms, resin, or color you will be consuming to the lot.
![](./img/label.png)
![](/img/ocp//label.png)
## Consuming new manual material via LST.
@@ -58,7 +59,7 @@ Click on material helper on the left side bar.
Enter the lot and running number and click consume, the card also comes with basic insturctions.
![](./img/lst-consume.png)
![](/img/ocp//lst-consume.png)
This will do the exact same process as using the scanner.
@@ -75,7 +76,7 @@ then you will want to add the enter the running number and the original quantity
label example to show where to look
![](./img/labelQty.png)
![](/img/ocp/labelQty.png)
NOTE: preforms have there quantity on the label as well and you can still use the external running number(iowas perform running numebr) to move to the next lot.
@@ -83,15 +84,15 @@ Last part you will need is the lot number you will be moving the material too.
Like in the consume lst comes with basic insturctions as well.
![](./img/lotTransfer.png)
![](/img/ocp/lotTransfer.png)
Please see example errors that you could see when utlizeing the lotTransfer card.
![](./img/e1.png) ![](./img/e2.png) ![](./img/e3.png) ![](./img/e4.png)
![](/img/ocp/e1.png) ![](/img/ocp//e2.png) ![](/img/ocp/e3.png) ![](/img/ocp/e4.png)
The below specfic and very generic error is more than likely an input error. And that could be the running number is wrong and never actually was in the system, but in the event everything was checked and you still get the error please report by entering a helpdesk ticket.
![](./img/e5.png)
![](/img/ocp/e5.png)
## Manual return and consume
@@ -110,7 +111,7 @@ Grab your label you are wanting to move to the next lot
Note the running number and qty. you will not ever be able to reprint for more than the qty that is currenty on the label
![](./img/labelQty.png)
![](/img/ocp/labelQty.png)
next open up alpla label (any version of alpla label will work for this step) and click on the reprint tab.
@@ -120,13 +121,13 @@ NOTE: if you see the yellow triangle like in the below example this indicates th
please reach out to your manager or supervisor to ask for next steps on what to do.
![](./img/reprint-caution.png)
![](/img/ocp//reprint-caution.png)
Next take the newly printed label, a scanner, workorder, and location barcode.
scan
![](./img/returnBarcode.png)
![](/img/ocp/returnBarcode.png)
- Scan the unit (The label you reprinted).
- Scan the lane (location where you will be returning this material/preforms to)
@@ -136,10 +137,10 @@ Grab the new work order
Scan
![](./img/consumebarcode.png)
![](/img/ocp/consumebarcode.png)
- Scan the top bar code on the production order
![](./img/workorder.png)
![](/img/ocp/workorder.png)
- Scan the barcode of the label you reprinted

View File

@@ -33,7 +33,30 @@ const config: Config = {
// may want to replace "en" with "zh-Hans".
i18n: {
defaultLocale: "en",
locales: ["en"],
locales: ["en", "es"],
// localeConfigs: {
// en: {
// label: "English",
// direction: "ltr",
// htmlLang: "en-US",
// calendar: "gregory",
// path: "en",
// },
// es: {
// label: "Español",
// direction: "ltr",
// htmlLang: "es-ES",
// calendar: "gregory",
// path: "es",
// },
// de: {
// label: "Deutsch",
// direction: "ltr",
// htmlLang: "de-DE",
// calendar: "gregory",
// path: "de",
// },
// },
},
presets: [
@@ -92,6 +115,10 @@ const config: Config = {
// label: "GitHub",
// position: "right",
// },
// {
// type: "localeDropdown",
// position: "right",
// },
],
},
footer: {

View File

@@ -14,6 +14,11 @@ import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
*/
const sidebars: SidebarsConfig = {
// By default, Docusaurus generates a sidebar from the docs folder structure
// docsSidebar: [
// { type: "doc", id: "intro" },
// { type: "doc", id: "install" },
// { type: "doc", id: "ocp/ocp" },
// ],
docsSidebar: [{ type: "autogenerated", dirName: "." }],
// But you can create a sidebar manually

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

View File

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 217 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

@@ -6,7 +6,7 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev:app": "dotenvx run -f .env -- tsx watch app/src/main.ts",
"dev:docs": "cd lstDocs && npm start",
"dev:docs": "npm run translateDocs && cd lstDocs && npm start",
"dev:front": "cd frontend && npm run dev",
"dev": "npm run dev:app",
"copy:docs": "node scripts/lstDocCopy.mjs",
@@ -26,7 +26,8 @@
"commit": "cz",
"deploy": "standard-version --conventional-commits && npm run build",
"db:migrate": "npx drizzle-kit push --config=drizzle-dev.config.ts",
"db:generate": "npx drizzle-kit generate --config=drizzle-dev.config.ts"
"db:generate": "npx drizzle-kit generate --config=drizzle-dev.config.ts",
"translateDocs": "cd scripts && node translateScript.js"
},
"repository": {
"type": "git",

View File

@@ -0,0 +1,88 @@
// scripts/sync-translations.js
import fs from "fs";
import path from "path";
const locales = ["en", "es", "de"];
const docsDir = path.join(process.cwd(), "../lstDocs/docs"); // canonical English docs
const i18nDir = path.join(process.cwd(), "../lstDocs/i18n"); // output localized docs
const langDir = path.join(process.cwd(), "../lang"); // json translations
// load translations
const translations = {};
for (const locale of locales) {
const filePath = path.join(langDir, `${locale}.json`);
translations[locale] = JSON.parse(fs.readFileSync(filePath, "utf8"));
}
// lookup helper with English fallback
function t(key, locale) {
return translations[locale][key] || translations["en"][key] || key;
}
// copy directory recursively
function copyDir(src, dest) {
if (!fs.existsSync(src)) return;
fs.mkdirSync(dest, { recursive: true });
for (const item of fs.readdirSync(src)) {
const s = path.join(src, item);
const d = path.join(dest, item);
const stat = fs.statSync(s);
if (stat.isDirectory()) copyDir(s, d);
else fs.copyFileSync(s, d);
}
}
// recursive doc processor
function processDir(srcDir, relDir = "") {
for (const item of fs.readdirSync(srcDir, { withFileTypes: true })) {
const srcPath = path.join(srcDir, item.name);
const relPath = path.join(relDir, item.name);
if (item.isDirectory()) {
processDir(srcPath, relPath);
continue;
}
if (item.isFile() && item.name.endsWith(".md")) {
const baseContent = fs.readFileSync(srcPath, "utf8");
for (const locale of locales) {
// replace keys with translations
const localizedContent = baseContent.replace(
/([a-z]+(\.[a-z]+)+)/g,
(match) => t(match, locale)
);
// output directory preserves structure
const outDir = path.join(
i18nDir,
locale,
"docusaurus-plugin-content-docs/current",
relDir
);
fs.mkdirSync(outDir, { recursive: true });
const outFile = path.join(outDir, item.name);
fs.writeFileSync(outFile, localizedContent, "utf8");
}
}
// if there's an "img" folder alongside docs, copy it once for each locale
if (item.isDirectory() && item.name === "img") {
for (const locale of locales) {
const outDir = path.join(
i18nDir,
locale,
"docusaurus-plugin-content-docs/current",
relDir,
"img"
);
copyDir(srcPath, outDir);
}
}
}
}
// run
processDir(docsDir);

View File

@@ -17,7 +17,14 @@
"include": [
"app/src",
"scripts/**/*.ts",
"database/testFiles/test-tiPostOrders.ts"
"database/testFiles/test-tiPostOrders.ts",
"scripts/translateScript.js"
],
"exclude": ["node_modules", "frontend", "dist", "lstDocs","database/testFiles"]
"exclude": [
"node_modules",
"frontend",
"dist",
"lstDocs",
"database/testFiles"
]
}