2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-16 12:03:08 +00:00

[PUI] Fix translation of model type strings (#8093)

* Fix dynamic translation of ModelType labels

- Cannot be stored as a const, as the locale changes dynamically
- Return translated labels via lookup function

* Tweak inline rendering functions
This commit is contained in:
Oliver 2024-09-09 13:21:50 +10:00 committed by GitHub
parent 4082d6e0ad
commit a8a3266382
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 173 additions and 72 deletions

View File

@ -39,7 +39,7 @@ import { useUserSettingsState } from '../../states/SettingsState';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { Boundary } from '../Boundary'; import { Boundary } from '../Boundary';
import { RenderInstance } from '../render/Instance'; import { RenderInstance } from '../render/Instance';
import { ModelInformationDict } from '../render/ModelType'; import { ModelInformationDict, getModelInfo } from '../render/ModelType';
// Define type for handling individual search queries // Define type for handling individual search queries
type SearchQuery = { type SearchQuery = {
@ -65,7 +65,7 @@ function QueryResultGroup({
return null; return null;
} }
const model = ModelInformationDict[query.model]; const model = getModelInfo(query.model);
return ( return (
<Paper shadow="sm" radius="xs" p="md" key={`paper-${query.model}`}> <Paper shadow="sm" radius="xs" p="md" key={`paper-${query.model}`}>

View File

@ -1,3 +1,4 @@
import { Text } from '@mantine/core';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
@ -70,7 +71,9 @@ export function RenderSupplierPart(
primary={supplier?.name} primary={supplier?.name}
secondary={instance.SKU} secondary={instance.SKU}
image={part?.thumbnail ?? part?.image} image={part?.thumbnail ?? part?.image}
suffix={part.full_name} suffix={
part.full_name ? <Text size="sm">{part.full_name}</Text> : undefined
}
url={ url={
props.link props.link
? getDetailUrl(ModelType.supplierpart, instance.pk) ? getDetailUrl(ModelType.supplierpart, instance.pk)
@ -95,7 +98,9 @@ export function RenderManufacturerPart(
{...props} {...props}
primary={manufacturer.name} primary={manufacturer.name}
secondary={instance.MPN} secondary={instance.MPN}
suffix={part.full_name} suffix={
part.full_name ? <Text size="sm">{part.full_name}</Text> : undefined
}
image={manufacturer?.thumnbnail ?? manufacturer.image} image={manufacturer?.thumnbnail ?? manufacturer.image}
url={ url={
props.link props.link

View File

@ -4,8 +4,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
export interface ModelInformationInterface { export interface ModelInformationInterface {
label: string;
label_multiple: string;
url_overview?: string; url_overview?: string;
url_detail?: string; url_detail?: string;
api_endpoint: ApiEndpoints; api_endpoint: ApiEndpoints;
@ -13,14 +11,19 @@ export interface ModelInformationInterface {
admin_url?: string; admin_url?: string;
} }
// Interface which includes dynamically translated labels
export interface ModelInformationInterfaceWithLabel
extends ModelInformationInterface {
label: string;
label_multiple: string;
}
export type ModelDict = { export type ModelDict = {
[key in keyof typeof ModelType]: ModelInformationInterface; [key in keyof typeof ModelType]: ModelInformationInterface;
}; };
export const ModelInformationDict: ModelDict = { export const ModelInformationDict: ModelDict = {
part: { part: {
label: t`Part`,
label_multiple: t`Parts`,
url_overview: '/part', url_overview: '/part',
url_detail: '/part/:pk/', url_detail: '/part/:pk/',
cui_detail: '/part/:pk/', cui_detail: '/part/:pk/',
@ -28,22 +31,16 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/part/part/' admin_url: '/part/part/'
}, },
partparametertemplate: { partparametertemplate: {
label: t`Part Parameter Template`,
label_multiple: t`Part Parameter Templates`,
url_overview: '/partparametertemplate', url_overview: '/partparametertemplate',
url_detail: '/partparametertemplate/:pk/', url_detail: '/partparametertemplate/:pk/',
api_endpoint: ApiEndpoints.part_parameter_template_list api_endpoint: ApiEndpoints.part_parameter_template_list
}, },
parttesttemplate: { parttesttemplate: {
label: t`Part Test Template`,
label_multiple: t`Part Test Templates`,
url_overview: '/parttesttemplate', url_overview: '/parttesttemplate',
url_detail: '/parttesttemplate/:pk/', url_detail: '/parttesttemplate/:pk/',
api_endpoint: ApiEndpoints.part_test_template_list api_endpoint: ApiEndpoints.part_test_template_list
}, },
supplierpart: { supplierpart: {
label: t`Supplier Part`,
label_multiple: t`Supplier Parts`,
url_overview: '/supplierpart', url_overview: '/supplierpart',
url_detail: '/purchasing/supplier-part/:pk/', url_detail: '/purchasing/supplier-part/:pk/',
cui_detail: '/supplier-part/:pk/', cui_detail: '/supplier-part/:pk/',
@ -51,8 +48,6 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/company/supplierpart/' admin_url: '/company/supplierpart/'
}, },
manufacturerpart: { manufacturerpart: {
label: t`Manufacturer Part`,
label_multiple: t`Manufacturer Parts`,
url_overview: '/manufacturerpart', url_overview: '/manufacturerpart',
url_detail: '/purchasing/manufacturer-part/:pk/', url_detail: '/purchasing/manufacturer-part/:pk/',
cui_detail: '/manufacturer-part/:pk/', cui_detail: '/manufacturer-part/:pk/',
@ -60,8 +55,6 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/company/manufacturerpart/' admin_url: '/company/manufacturerpart/'
}, },
partcategory: { partcategory: {
label: t`Part Category`,
label_multiple: t`Part Categories`,
url_overview: '/part/category', url_overview: '/part/category',
url_detail: '/part/category/:pk/', url_detail: '/part/category/:pk/',
cui_detail: '/part/category/:pk/', cui_detail: '/part/category/:pk/',
@ -69,8 +62,6 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/part/partcategory/' admin_url: '/part/partcategory/'
}, },
stockitem: { stockitem: {
label: t`Stock Item`,
label_multiple: t`Stock Items`,
url_overview: '/stock/item', url_overview: '/stock/item',
url_detail: '/stock/item/:pk/', url_detail: '/stock/item/:pk/',
cui_detail: '/stock/item/:pk/', cui_detail: '/stock/item/:pk/',
@ -78,8 +69,6 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/stock/stockitem/' admin_url: '/stock/stockitem/'
}, },
stocklocation: { stocklocation: {
label: t`Stock Location`,
label_multiple: t`Stock Locations`,
url_overview: '/stock/location', url_overview: '/stock/location',
url_detail: '/stock/location/:pk/', url_detail: '/stock/location/:pk/',
cui_detail: '/stock/location/:pk/', cui_detail: '/stock/location/:pk/',
@ -87,18 +76,12 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/stock/stocklocation/' admin_url: '/stock/stocklocation/'
}, },
stocklocationtype: { stocklocationtype: {
label: t`Stock Location Type`,
label_multiple: t`Stock Location Types`,
api_endpoint: ApiEndpoints.stock_location_type_list api_endpoint: ApiEndpoints.stock_location_type_list
}, },
stockhistory: { stockhistory: {
label: t`Stock History`,
label_multiple: t`Stock Histories`,
api_endpoint: ApiEndpoints.stock_tracking_list api_endpoint: ApiEndpoints.stock_tracking_list
}, },
build: { build: {
label: t`Build`,
label_multiple: t`Builds`,
url_overview: '/build', url_overview: '/build',
url_detail: '/build/:pk/', url_detail: '/build/:pk/',
cui_detail: '/build/:pk/', cui_detail: '/build/:pk/',
@ -106,21 +89,15 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/build/build/' admin_url: '/build/build/'
}, },
buildline: { buildline: {
label: t`Build Line`,
label_multiple: t`Build Lines`,
url_overview: '/build/line', url_overview: '/build/line',
url_detail: '/build/line/:pk/', url_detail: '/build/line/:pk/',
cui_detail: '/build/line/:pk/', cui_detail: '/build/line/:pk/',
api_endpoint: ApiEndpoints.build_line_list api_endpoint: ApiEndpoints.build_line_list
}, },
builditem: { builditem: {
label: t`Build Item`,
label_multiple: t`Build Items`,
api_endpoint: ApiEndpoints.build_item_list api_endpoint: ApiEndpoints.build_item_list
}, },
company: { company: {
label: t`Company`,
label_multiple: t`Companies`,
url_overview: '/company', url_overview: '/company',
url_detail: '/company/:pk/', url_detail: '/company/:pk/',
cui_detail: '/company/:pk/', cui_detail: '/company/:pk/',
@ -128,15 +105,11 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/company/company/' admin_url: '/company/company/'
}, },
projectcode: { projectcode: {
label: t`Project Code`,
label_multiple: t`Project Codes`,
url_overview: '/project-code', url_overview: '/project-code',
url_detail: '/project-code/:pk/', url_detail: '/project-code/:pk/',
api_endpoint: ApiEndpoints.project_code_list api_endpoint: ApiEndpoints.project_code_list
}, },
purchaseorder: { purchaseorder: {
label: t`Purchase Order`,
label_multiple: t`Purchase Orders`,
url_overview: '/purchasing/purchase-order', url_overview: '/purchasing/purchase-order',
url_detail: '/purchasing/purchase-order/:pk/', url_detail: '/purchasing/purchase-order/:pk/',
cui_detail: '/order/purchase-order/:pk/', cui_detail: '/order/purchase-order/:pk/',
@ -144,13 +117,9 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/order/purchaseorder/' admin_url: '/order/purchaseorder/'
}, },
purchaseorderlineitem: { purchaseorderlineitem: {
label: t`Purchase Order Line`,
label_multiple: t`Purchase Order Lines`,
api_endpoint: ApiEndpoints.purchase_order_line_list api_endpoint: ApiEndpoints.purchase_order_line_list
}, },
salesorder: { salesorder: {
label: t`Sales Order`,
label_multiple: t`Sales Orders`,
url_overview: '/sales/sales-order', url_overview: '/sales/sales-order',
url_detail: '/sales/sales-order/:pk/', url_detail: '/sales/sales-order/:pk/',
cui_detail: '/order/sales-order/:pk/', cui_detail: '/order/sales-order/:pk/',
@ -158,15 +127,11 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/order/salesorder/' admin_url: '/order/salesorder/'
}, },
salesordershipment: { salesordershipment: {
label: t`Sales Order Shipment`,
label_multiple: t`Sales Order Shipments`,
url_overview: '/salesordershipment', url_overview: '/salesordershipment',
url_detail: '/salesordershipment/:pk/', url_detail: '/salesordershipment/:pk/',
api_endpoint: ApiEndpoints.sales_order_shipment_list api_endpoint: ApiEndpoints.sales_order_shipment_list
}, },
returnorder: { returnorder: {
label: t`Return Order`,
label_multiple: t`Return Orders`,
url_overview: '/sales/return-order', url_overview: '/sales/return-order',
url_detail: '/sales/return-order/:pk/', url_detail: '/sales/return-order/:pk/',
cui_detail: '/order/return-order/:pk/', cui_detail: '/order/return-order/:pk/',
@ -174,86 +139,216 @@ export const ModelInformationDict: ModelDict = {
admin_url: '/order/returnorder/' admin_url: '/order/returnorder/'
}, },
returnorderlineitem: { returnorderlineitem: {
label: t`Return Order Line Item`,
label_multiple: t`Return Order Line Items`,
api_endpoint: ApiEndpoints.return_order_line_list api_endpoint: ApiEndpoints.return_order_line_list
}, },
address: { address: {
label: t`Address`,
label_multiple: t`Addresses`,
url_overview: '/address', url_overview: '/address',
url_detail: '/address/:pk/', url_detail: '/address/:pk/',
api_endpoint: ApiEndpoints.address_list api_endpoint: ApiEndpoints.address_list
}, },
contact: { contact: {
label: t`Contact`,
label_multiple: t`Contacts`,
url_overview: '/contact', url_overview: '/contact',
url_detail: '/contact/:pk/', url_detail: '/contact/:pk/',
api_endpoint: ApiEndpoints.contact_list api_endpoint: ApiEndpoints.contact_list
}, },
owner: { owner: {
label: t`Owner`,
label_multiple: t`Owners`,
url_overview: '/owner', url_overview: '/owner',
url_detail: '/owner/:pk/', url_detail: '/owner/:pk/',
api_endpoint: ApiEndpoints.owner_list api_endpoint: ApiEndpoints.owner_list
}, },
user: { user: {
label: t`User`,
label_multiple: t`Users`,
url_overview: '/user', url_overview: '/user',
url_detail: '/user/:pk/', url_detail: '/user/:pk/',
api_endpoint: ApiEndpoints.user_list api_endpoint: ApiEndpoints.user_list
}, },
group: { group: {
label: t`Group`,
label_multiple: t`Groups`,
url_overview: '/user/group', url_overview: '/user/group',
url_detail: '/user/group-:pk', url_detail: '/user/group-:pk',
api_endpoint: ApiEndpoints.group_list, api_endpoint: ApiEndpoints.group_list,
admin_url: '/auth/group/' admin_url: '/auth/group/'
}, },
importsession: { importsession: {
label: t`Import Session`,
label_multiple: t`Import Sessions`,
url_overview: '/import', url_overview: '/import',
url_detail: '/import/:pk/', url_detail: '/import/:pk/',
api_endpoint: ApiEndpoints.import_session_list api_endpoint: ApiEndpoints.import_session_list
}, },
labeltemplate: { labeltemplate: {
label: t`Label Template`,
label_multiple: t`Label Templates`,
url_overview: '/labeltemplate', url_overview: '/labeltemplate',
url_detail: '/labeltemplate/:pk/', url_detail: '/labeltemplate/:pk/',
api_endpoint: ApiEndpoints.label_list api_endpoint: ApiEndpoints.label_list
}, },
reporttemplate: { reporttemplate: {
label: t`Report Template`,
label_multiple: t`Report Templates`,
url_overview: '/reporttemplate', url_overview: '/reporttemplate',
url_detail: '/reporttemplate/:pk/', url_detail: '/reporttemplate/:pk/',
api_endpoint: ApiEndpoints.report_list api_endpoint: ApiEndpoints.report_list
}, },
pluginconfig: { pluginconfig: {
label: t`Plugin Configuration`,
label_multiple: t`Plugin Configurations`,
url_overview: '/pluginconfig', url_overview: '/pluginconfig',
url_detail: '/pluginconfig/:pk/', url_detail: '/pluginconfig/:pk/',
api_endpoint: ApiEndpoints.plugin_list api_endpoint: ApiEndpoints.plugin_list
}, },
contenttype: { contenttype: {
label: t`Content Type`,
label_multiple: t`Content Types`,
api_endpoint: ApiEndpoints.content_type_list api_endpoint: ApiEndpoints.content_type_list
} }
}; };
/*
* Return the translated singular label for a particular model type.
* Note: This *must* be called dynamically, as the translation is not static.
*/
export function getModelLabel(type: ModelType): string {
switch (type) {
case ModelType.part:
return t`Part`;
case ModelType.partparametertemplate:
return t`Part Parameter Template`;
case ModelType.parttesttemplate:
return t`Part Test Template`;
case ModelType.supplierpart:
return t`Supplier Part`;
case ModelType.manufacturerpart:
return t`Manufacturer Part`;
case ModelType.partcategory:
return t`Part Category`;
case ModelType.stockitem:
return t`Stock Item`;
case ModelType.stocklocation:
return t`Stock Location`;
case ModelType.stocklocationtype:
return t`Stock Location Type`;
case ModelType.stockhistory:
return t`Stock History`;
case ModelType.build:
return t`Build Order`;
case ModelType.buildline:
return t`Build Line`;
case ModelType.builditem:
return t`Build Item`;
case ModelType.company:
return t`Company`;
case ModelType.projectcode:
return t`Project Code`;
case ModelType.purchaseorder:
return t`Purchase Order`;
case ModelType.purchaseorderlineitem:
return t`Purchase Order Line Item`;
case ModelType.salesorder:
return t`Sales Order`;
case ModelType.salesordershipment:
return t`Sales Order Shipment`;
case ModelType.returnorder:
return t`Return Order`;
case ModelType.returnorderlineitem:
return t`Return Order Line Item`;
case ModelType.address:
return t`Address`;
case ModelType.contact:
return t`Contact`;
case ModelType.owner:
return t`Owner`;
case ModelType.user:
return t`User`;
case ModelType.group:
return t`Group`;
case ModelType.importsession:
return t`Import Session`;
case ModelType.labeltemplate:
return t`Label Template`;
case ModelType.reporttemplate:
return t`Report Template`;
case ModelType.pluginconfig:
return t`Plugin Configuration`;
case ModelType.contenttype:
return t`Content Type`;
default:
return t`Unknown Model`;
}
}
/*
* Return the translated plural label for a particular model type.
* Note: This *must* be called dynamically, as the translation is not static.
*/
export function getModelLabelMultiple(type: ModelType): string {
switch (type) {
case ModelType.part:
return t`Parts`;
case ModelType.partparametertemplate:
return t`Part Parameter Templates`;
case ModelType.parttesttemplate:
return t`Part Test Templates`;
case ModelType.supplierpart:
return t`Supplier Parts`;
case ModelType.manufacturerpart:
return t`Manufacturer Parts`;
case ModelType.partcategory:
return t`Part Categories`;
case ModelType.stockitem:
return t`Stock Items`;
case ModelType.stocklocation:
return t`Stock Locations`;
case ModelType.stocklocationtype:
return t`Stock Location Types`;
case ModelType.stockhistory:
return t`Stock Histories`;
case ModelType.build:
return t`Build Orders`;
case ModelType.buildline:
return t`Build Lines`;
case ModelType.builditem:
return t`Build Items`;
case ModelType.company:
return t`Companies`;
case ModelType.projectcode:
return t`Project Codes`;
case ModelType.purchaseorder:
return t`Purchase Orders`;
case ModelType.purchaseorderlineitem:
return t`Purchase Order Line Items`;
case ModelType.salesorder:
return t`Sales Orders`;
case ModelType.salesordershipment:
return t`Sales Order Shipments`;
case ModelType.returnorder:
return t`Return Orders`;
case ModelType.returnorderlineitem:
return t`Return Order Line Items`;
case ModelType.address:
return t`Addresses`;
case ModelType.contact:
return t`Contacts`;
case ModelType.owner:
return t`Owners`;
case ModelType.user:
return t`Users`;
case ModelType.group:
return t`Groups`;
case ModelType.importsession:
return t`Import Sessions`;
case ModelType.labeltemplate:
return t`Label Templates`;
case ModelType.reporttemplate:
return t`Report Templates`;
case ModelType.pluginconfig:
return t`Plugin Configurations`;
case ModelType.contenttype:
return t`Content Types`;
default:
return t`Unknown Models`;
}
}
/* /*
* Extract model definition given the provided type * Extract model definition given the provided type
* @param type - ModelType to extract information from * @param type - ModelType to extract information from
* @returns ModelInformationInterface * @returns ModelInformationInterfaceWithLabel
*/ */
export function getModelInfo(type: ModelType): ModelInformationInterface { export function getModelInfo(
return ModelInformationDict[type]; type: ModelType
): ModelInformationInterfaceWithLabel {
return {
...ModelInformationDict[type],
label: getModelLabel(type),
label_multiple: getModelLabelMultiple(type)
};
} }

View File

@ -1,4 +1,5 @@
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Text } from '@mantine/core';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
@ -66,7 +67,7 @@ export function RenderStockItem(
<RenderInlineModel <RenderInlineModel
{...props} {...props}
primary={instance.part_detail?.full_name} primary={instance.part_detail?.full_name}
suffix={quantity_string} suffix={<Text size="sm">{quantity_string}</Text>}
image={instance.part_detail?.thumbnail || instance.part_detail?.image} image={instance.part_detail?.thumbnail || instance.part_detail?.image}
url={ url={
props.link ? getDetailUrl(ModelType.stockitem, instance.pk) : undefined props.link ? getDetailUrl(ModelType.stockitem, instance.pk) : undefined