feat(i18n): localize inventory items UI

This commit is contained in:
2026-06-13 11:12:02 +02:00
parent 9f7d1b8ef8
commit 964b1648ca
12 changed files with 414 additions and 33 deletions
+59
View File
@@ -0,0 +1,59 @@
import { expect, type Page, test } from "@playwright/test"
async function setLocaleCookie(
page: Page,
locale: "en" | "es",
baseURL?: string,
) {
await page.context().addCookies([
{
name: "stock-manager-locale",
value: locale,
url: baseURL ?? "http://127.0.0.1:3100",
},
])
}
async function signInAsAdmin(page: Page, baseURL?: string) {
await setLocaleCookie(page, "en", baseURL)
await page.goto("/login")
await page.getByLabel("Username").fill("admin")
await page.getByLabel("Password").fill("admin-password")
await page.getByRole("button", { name: "Sign In" }).click()
await expect(page).toHaveURL("/")
}
test.describe("inventory items localization", () => {
test("renders item list and new form UI copy in Spanish", async ({
baseURL,
page,
}) => {
await signInAsAdmin(page, baseURL)
await setLocaleCookie(page, "es", baseURL)
await page.goto("/inventory/items")
await expect(page.locator("html")).toHaveAttribute("lang", "es")
await expect(page.getByRole("heading", { name: "Artículos" })).toBeVisible()
await expect(
page.getByRole("link", { name: /Agregar artículo/ }),
).toBeVisible()
await expect(page.getByText("No se encontraron artículos.")).toBeVisible()
await page.goto("/inventory/items/new")
await expect(
page.getByRole("heading", { name: "Nuevo artículo" }),
).toBeVisible()
await expect(page.getByLabel("Nombre")).toBeVisible()
await expect(page.getByPlaceholder("Nombre del artículo")).toBeVisible()
await expect(page.getByLabel("Categoría")).toBeVisible()
await expect(page.locator("select#categoryId")).toContainText(
"Selecciona una categoría",
)
await expect(page.getByLabel("Stock")).toBeVisible()
await expect(
page.getByRole("button", { name: "Crear artículo" }),
).toBeVisible()
})
})
+142
View File
@@ -266,6 +266,148 @@ describe("i18n dictionaries", () => {
})
})
it("provides localized inventory item copy for English and Spanish", () => {
expect(getDictionary("en").inventory.items).toEqual({
list: {
title: "Items",
addLabel: "Add Item",
empty: "No items found.",
columns: {
name: "Name",
category: "Category",
assets: "Assets",
stock: "Stock",
actions: "Actions",
},
actions: {
view: "View item",
edit: "Edit item",
delete: "Delete item",
},
},
detail: {
notFound: "Item not found",
labels: {
category: "Category",
stock: "Stock",
},
},
new: {
title: "New Item",
},
edit: {
title: "Edit Item",
notFound: "Item not found",
hasAssetsWarning: "This item has already assets assigned to it.",
},
form: {
nameLabel: "Name",
namePlaceholder: "Item name",
categoryLabel: "Category",
categoryPlaceholder: "Select a category",
stockLabel: "Stock",
stockPlaceholder: "0",
createSubmit: "Create Item",
updateSubmit: "Update Item",
},
delete: {
label: "Delete item",
pending: "Deleting...",
unknownError: "Unknown error",
},
actions: {
createSuccess: "Item created successfully!",
createFailure: "Error creating item",
updateSuccess: "Item updated successfully!",
updateFailure: "Failed to update item",
deleteSuccess: "Item deleted successfully!",
deleteFailure: "Failed to delete item",
duplicateName: "Item already exists",
notFound: "Item not found",
hasAssets: "Cannot delete item with assets",
hasStock: "Cannot delete item with stock",
invalidStock: "Invalid stock",
negativeStock: "Stock cannot be negative",
},
schema: {
nameRequired: "Name is required",
categoryRequired: "Category is required",
stockRequired: "Stock is required",
itemRequired: "Item is required",
},
})
expect(getDictionary("es").inventory.items).toEqual({
list: {
title: "Artículos",
addLabel: "Agregar artículo",
empty: "No se encontraron artículos.",
columns: {
name: "Nombre",
category: "Categoría",
assets: "Activos",
stock: "Stock",
actions: "Acciones",
},
actions: {
view: "Ver artículo",
edit: "Editar artículo",
delete: "Eliminar artículo",
},
},
detail: {
notFound: "Artículo no encontrado",
labels: {
category: "Categoría",
stock: "Stock",
},
},
new: {
title: "Nuevo artículo",
},
edit: {
title: "Editar artículo",
notFound: "Artículo no encontrado",
hasAssetsWarning: "Este artículo ya tiene activos asignados.",
},
form: {
nameLabel: "Nombre",
namePlaceholder: "Nombre del artículo",
categoryLabel: "Categoría",
categoryPlaceholder: "Selecciona una categoría",
stockLabel: "Stock",
stockPlaceholder: "0",
createSubmit: "Crear artículo",
updateSubmit: "Actualizar artículo",
},
delete: {
label: "Eliminar artículo",
pending: "Eliminando...",
unknownError: "Error desconocido",
},
actions: {
createSuccess: "Artículo creado correctamente",
createFailure: "Error al crear el artículo",
updateSuccess: "Artículo actualizado correctamente",
updateFailure: "Error al actualizar el artículo",
deleteSuccess: "Artículo eliminado correctamente",
deleteFailure: "Error al eliminar el artículo",
duplicateName: "El artículo ya existe",
notFound: "Artículo no encontrado",
hasAssets: "No se puede eliminar un artículo con activos",
hasStock: "No se puede eliminar un artículo con stock",
invalidStock: "Stock inválido",
negativeStock: "El stock no puede ser negativo",
},
schema: {
nameRequired: "El nombre es obligatorio",
categoryRequired: "La categoría es obligatoria",
stockRequired: "El stock es obligatorio",
itemRequired: "El artículo es obligatorio",
},
})
})
it("keeps dashboard home dictionary keys aligned across locales", () => {
expect(getDictionary("en").dashboardHome).toEqual({
heading: "Dashboard",