mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-01-13 13:49:33 +00:00
JSON Importer mit Minimaldaten weiterentwickeln. Validierung mit Violations einführen und beim Import-Versuch zusätzlich mit ausgeben
This commit is contained in:
parent
b227bacdb0
commit
23e4b00e77
16 changed files with 984 additions and 98 deletions
|
|
@ -29,7 +29,6 @@ use App\Entity\Parts\Part;
|
|||
use App\Form\AssemblySystem\AssemblyAddPartsType;
|
||||
use App\Form\AssemblySystem\AssemblyBuildType;
|
||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
||||
use App\Repository\PartRepository;
|
||||
use App\Services\ImportExportSystem\BOMImporter;
|
||||
use App\Services\AssemblySystem\AssemblyBuildHelper;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
|
@ -52,14 +51,10 @@ use function Symfony\Component\Translation\t;
|
|||
#[Route(path: '/assembly')]
|
||||
class AssemblyController extends AbstractController
|
||||
{
|
||||
private PartRepository $partRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly DataTableFactory $dataTableFactory,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly TranslatorInterface $translator,
|
||||
) {
|
||||
$this->partRepository = $this->entityManager->getRepository(Part::class);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/info', name: 'assembly_info', requirements: ['id' => '\d+'])]
|
||||
|
|
@ -161,15 +156,14 @@ class AssemblyController extends AbstractController
|
|||
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
|
||||
//Clear existing BOM entries if requested
|
||||
// Clear existing entries if requested
|
||||
if ($form->get('clear_existing_bom')->getData()) {
|
||||
$assembly->getBomEntries()->clear();
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
||||
try {
|
||||
$entries = $BOMImporter->importFileIntoAssembly($form->get('file')->getData(), $assembly, [
|
||||
$importerResult = $BOMImporter->importFileIntoAssembly($form->get('file')->getData(), $assembly, [
|
||||
'type' => $form->get('type')->getData(),
|
||||
]);
|
||||
|
||||
|
|
@ -177,24 +171,17 @@ class AssemblyController extends AbstractController
|
|||
$errors = $validator->validateProperty($assembly, 'bom_entries');
|
||||
|
||||
//If no validation errors occured, save the changes and redirect to edit page
|
||||
if (count ($errors) === 0) {
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry instanceof AssemblyBOMEntry && $entry->getPart() !== null) {
|
||||
$part = $entry->getPart();
|
||||
if ($part->getID() === null) {
|
||||
$this->partRepository->save($part);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count ($errors) === 0 && $importerResult->getViolations()->count() === 0) {
|
||||
$entries = $importerResult->getBomEntries();
|
||||
|
||||
$this->addFlash('success', t('assembly.bom_import.flash.success', ['%count%' => count($entries)]));
|
||||
$entityManager->flush();
|
||||
|
||||
return $this->redirectToRoute('assembly_edit', ['id' => $assembly->getID()]);
|
||||
}
|
||||
|
||||
//When we get here, there were validation errors
|
||||
//Show validation errors
|
||||
$this->addFlash('error', t('assembly.bom_import.flash.invalid_entries'));
|
||||
|
||||
} catch (\UnexpectedValueException|\RuntimeException|SyntaxError $e) {
|
||||
$this->addFlash('error', t('assembly.bom_import.flash.invalid_file', ['%message%' => $e->getMessage()]));
|
||||
}
|
||||
|
|
@ -226,7 +213,8 @@ class AssemblyController extends AbstractController
|
|||
'assembly' => $assembly,
|
||||
'jsonTemplate' => $jsonTemplate,
|
||||
'form' => $form,
|
||||
'errors' => $errors ?? null,
|
||||
'validationErrors' => $errors ?? null,
|
||||
'importerErrors' => isset($importerResult) ? $importerResult->getViolations() : null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,9 @@ use League\Csv\Reader;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use RuntimeException;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use UnexpectedValueException;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
|
||||
/**
|
||||
* @see \App\Tests\Services\ImportExportSystem\BOMImporterTest
|
||||
|
|
@ -57,16 +58,21 @@ class BOMImporter
|
|||
5 => 'Supplier and ref',
|
||||
];
|
||||
|
||||
private readonly PartRepository $partRepository;
|
||||
private string $jsonRoot = '';
|
||||
|
||||
private readonly ManufacturerRepository $manufacturerRepository;
|
||||
private PartRepository $partRepository;
|
||||
|
||||
private readonly CategoryRepository $categoryRepository;
|
||||
private ManufacturerRepository $manufacturerRepository;
|
||||
|
||||
private readonly DBElementRepository $assemblyBOMEntryRepository;
|
||||
private CategoryRepository $categoryRepository;
|
||||
|
||||
private DBElementRepository $assemblyBOMEntryRepository;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly BOMValidationService $validationService
|
||||
) {
|
||||
|
|
@ -74,6 +80,7 @@ class BOMImporter
|
|||
$this->manufacturerRepository = $entityManager->getRepository(Manufacturer::class);
|
||||
$this->categoryRepository = $entityManager->getRepository(Category::class);
|
||||
$this->assemblyBOMEntryRepository = $entityManager->getRepository(AssemblyBOMEntry::class);
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
protected function configureOptions(OptionsResolver $resolver): OptionsResolver
|
||||
|
|
@ -110,20 +117,21 @@ class BOMImporter
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts the given file into an array of BOM entries using the given options and save them into the given assembly.
|
||||
* Converts the given file into an ImporterResult with an array of BOM entries using the given options and save them into the given assembly.
|
||||
* The changes are not saved into the database yet.
|
||||
* @return AssemblyBOMEntry[]
|
||||
*/
|
||||
public function importFileIntoAssembly(File $file, Assembly $assembly, array $options): array
|
||||
public function importFileIntoAssembly(File $file, Assembly $assembly, array $options): ImporterResult
|
||||
{
|
||||
$bomEntries = $this->fileToBOMEntries($file, $options, AssemblyBOMEntry::class);
|
||||
$importerResult = $this->fileToImporterResult($file, $options, AssemblyBOMEntry::class);
|
||||
|
||||
//Assign the bom_entries to the assembly
|
||||
foreach ($bomEntries as $bom_entry) {
|
||||
$assembly->addBomEntry($bom_entry);
|
||||
if ($importerResult->getViolations()->count() === 0) {
|
||||
//Assign the bom_entries to the assembly
|
||||
foreach ($importerResult->getBomEntries() as $bomEntry) {
|
||||
$assembly->addBomEntry($bomEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return $bomEntries;
|
||||
return $importerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -152,6 +160,14 @@ class BOMImporter
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given file into an ImporterResult with an array of BOM entries using the given options.
|
||||
*/
|
||||
public function fileToImporterResult(File $file, array $options, string $objectType = ProjectBOMEntry::class): ImporterResult
|
||||
{
|
||||
return $this->stringToImporterResult($file->getContent(), $options, $objectType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import string data into an array of BOM entries, which are not yet assigned to a project.
|
||||
* @param string $data The data to import
|
||||
|
|
@ -164,6 +180,24 @@ class BOMImporter
|
|||
$resolver = $this->configureOptions($resolver);
|
||||
$options = $resolver->resolve($options);
|
||||
|
||||
return match ($options['type']) {
|
||||
'kicad_pcbnew' => $this->parseKiCADPCB($data, $options, $objectType)->getBomEntries(),
|
||||
default => throw new InvalidArgumentException('Invalid import type!'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Import string data into an array of BOM entries, which are not yet assigned to a project.
|
||||
* @param string $data The data to import
|
||||
* @param array $options An array of options
|
||||
* @return ProjectBOMEntry[]|AssemblyBOMEntry[] An array of imported entries
|
||||
*/
|
||||
public function stringToImporterResult(string $data, array $options, string $objectType = ProjectBOMEntry::class): ImporterResult
|
||||
{
|
||||
$resolver = new OptionsResolver();
|
||||
$resolver = $this->configureOptions($resolver);
|
||||
$options = $resolver->resolve($options);
|
||||
|
||||
return match ($options['type']) {
|
||||
'kicad_pcbnew' => $this->parseKiCADPCB($data, $objectType),
|
||||
'json' => $this->parseJson($data, $options, $objectType),
|
||||
|
|
@ -171,14 +205,14 @@ class BOMImporter
|
|||
};
|
||||
}
|
||||
|
||||
private function parseKiCADPCB(string $data, string $objectType = ProjectBOMEntry::class): array
|
||||
private function parseKiCADPCB(string $data, string $objectType = ProjectBOMEntry::class): ImporterResult
|
||||
{
|
||||
$result = new ImporterResult();
|
||||
|
||||
$csv = Reader::createFromString($data);
|
||||
$csv->setDelimiter(';');
|
||||
$csv->setHeaderOffset(0);
|
||||
|
||||
$bom_entries = [];
|
||||
|
||||
foreach ($csv->getRecords() as $offset => $entry) {
|
||||
//Translate the german field names to english
|
||||
$entry = $this->normalizeColumnNames($entry);
|
||||
|
|
@ -208,10 +242,10 @@ class BOMImporter
|
|||
$bom_entry->setComment($entry['Supplier and ref'] ?? '');
|
||||
$bom_entry->setQuantity((float) ($entry['Quantity'] ?? 1));
|
||||
|
||||
$bom_entries[] = $bom_entry;
|
||||
$result->addBomEntry($bom_entry);
|
||||
}
|
||||
|
||||
return $bom_entries;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -271,30 +305,47 @@ class BOMImporter
|
|||
return $this->validationService->validateBOMEntries($mapped_entries, $options);
|
||||
}
|
||||
|
||||
private function parseJson(string $data, array $options = [], string $objectType = ProjectBOMEntry::class): array
|
||||
private function parseJson(string $data, array $options = [], string $objectType = ProjectBOMEntry::class): ImporterResult
|
||||
{
|
||||
$result = [];
|
||||
$result = new ImporterResult();
|
||||
$this->jsonRoot = 'JSON Import for '.$objectType === ProjectBOMEntry::class ? 'Project' : 'Assembly';
|
||||
|
||||
$data = json_decode($data, true);
|
||||
|
||||
foreach ($data as $entry) {
|
||||
foreach ($data as $key => $entry) {
|
||||
// Check quantity
|
||||
if (!isset($entry['quantity'])) {
|
||||
throw new UnexpectedValueException('quantity missing');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.quantity.required',
|
||||
"entry[$key].quantity"
|
||||
));
|
||||
}
|
||||
if (!is_float($entry['quantity']) || $entry['quantity'] <= 0) {
|
||||
throw new UnexpectedValueException('quantity expected as float greater than 0.0');
|
||||
|
||||
if (isset($entry['quantity']) && (!is_float($entry['quantity']) || $entry['quantity'] <= 0)) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.quantity.float',
|
||||
"entry[$key].quantity",
|
||||
$entry['quantity']
|
||||
));
|
||||
}
|
||||
|
||||
// Check name
|
||||
if (isset($entry['name']) && !is_string($entry['name'])) {
|
||||
throw new UnexpectedValueException('name of part list entry expected as string');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.string.notEmpty',
|
||||
"entry[$key].name",
|
||||
$entry['name']
|
||||
));
|
||||
}
|
||||
|
||||
// Check if part is assigned with relevant information
|
||||
if (isset($entry['part'])) {
|
||||
if (!is_array($entry['part'])) {
|
||||
throw new UnexpectedValueException('The property "part" should be an array');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.array',
|
||||
"entry[$key].part",
|
||||
$entry['part']
|
||||
));
|
||||
}
|
||||
|
||||
$partIdValid = isset($entry['part']['id']) && is_int($entry['part']['id']) && $entry['part']['id'] > 0;
|
||||
|
|
@ -303,9 +354,12 @@ class BOMImporter
|
|||
$partIpnValid = isset($entry['part']['ipn']) && is_string($entry['part']['ipn']) && trim($entry['part']['ipn']) !== '';
|
||||
|
||||
if (!$partIdValid && !$partNameValid && !$partMpnrValid && !$partIpnValid) {
|
||||
throw new UnexpectedValueException(
|
||||
'The property "part" must have either assigned: "id" as integer greater than 0, "name", "mpnr", or "ipn" as non-empty string'
|
||||
);
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.subproperties',
|
||||
"entry[$key].part",
|
||||
$entry['part'],
|
||||
['%propertyString%' => '"id", "name", "mpnr", or "ipn"']
|
||||
));
|
||||
}
|
||||
|
||||
$part = $partIdValid ? $this->partRepository->findOneBy(['id' => $entry['part']['id']]) : null;
|
||||
|
|
@ -314,28 +368,71 @@ class BOMImporter
|
|||
$part = $part ?? ($partNameValid ? $this->partRepository->findOneBy(['name' => trim($entry['part']['name'])]) : null);
|
||||
|
||||
if ($part === null) {
|
||||
$part = new Part();
|
||||
$part->setName($entry['part']['name']);
|
||||
$value = sprintf('part.id: %s, part.mpnr: %s, part.ipn: %s, part.name: %s',
|
||||
isset($entry['part']['id']) ? '<strong>' . $entry['part']['id'] . '</strong>' : '-',
|
||||
isset($entry['part']['mpnr']) ? '<strong>' . $entry['part']['mpnr'] . '</strong>' : '-',
|
||||
isset($entry['part']['ipn']) ? '<strong>' . $entry['part']['ipn'] . '</strong>' : '-',
|
||||
isset($entry['part']['name']) ? '<strong>' . $entry['part']['name'] . '</strong>' : '-',
|
||||
);
|
||||
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.notFoundFor',
|
||||
"entry[$key].part",
|
||||
$entry['part'],
|
||||
['%value%' => $value]
|
||||
));
|
||||
}
|
||||
|
||||
if ($partNameValid && $part->getName() !== trim($entry['part']['name'])) {
|
||||
throw new RuntimeException(sprintf('Part name does not match exact the given name. Given for import: %s, found part: %s', $entry['part']['name'], $part->getName()));
|
||||
if ($partNameValid && $part !== null && isset($entry['part']['name']) && $part->getName() !== trim($entry['part']['name'])) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.noExactMatch',
|
||||
"entry[$key].part.name",
|
||||
$entry['part']['name'],
|
||||
[
|
||||
'%importValue%' => '<strong>' . $entry['part']['name'] . '</strong>',
|
||||
'%foundId%' => $part->getID(),
|
||||
'%foundValue%' => '<strong>' . $part->getName() . '</strong>'
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
if ($partIpnValid && $part->getManufacturerProductNumber() !== trim($entry['part']['mpnr'])) {
|
||||
throw new RuntimeException(sprintf('Part mpnr does not match exact the given mpnr. Given for import: %s, found part: %s', $entry['part']['mpnr'], $part->getManufacturerProductNumber()));
|
||||
if ($partMpnrValid && $part !== null && isset($entry['part']['mpnr']) && $part->getManufacturerProductNumber() !== trim($entry['part']['mpnr'])) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.noExactMatch',
|
||||
"entry[$key].part.mpnr",
|
||||
$entry['part']['mpnr'],
|
||||
[
|
||||
'%importValue%' => '<strong>' . $entry['part']['mpnr'] . '</strong>',
|
||||
'%foundId%' => $part->getID(),
|
||||
'%foundValue%' => '<strong>' . $part->getManufacturerProductNumber() . '</strong>'
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
if ($partIpnValid && $part->getIpn() !== trim($entry['part']['ipn'])) {
|
||||
throw new RuntimeException(sprintf('Part ipn does not match exact the given ipn. Given for import: %s, found part: %s', $entry['part']['ipn'], $part->getIpn()));
|
||||
if ($partIpnValid && $part !== null && isset($entry['part']['ipn']) && $part->getIpn() !== trim($entry['part']['ipn'])) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.noExactMatch',
|
||||
"entry[$key].part.ipn",
|
||||
$entry['part']['ipn'],
|
||||
[
|
||||
'%importValue%' => '<strong>' . $entry['part']['ipn'] . '</strong>',
|
||||
'%foundId%' => $part->getID(),
|
||||
'%foundValue%' => '<strong>' . $part->getIpn() . '</strong>'
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
// Part: Description check
|
||||
if (isset($entry['part']['description']) && !is_null($entry['part']['description'])) {
|
||||
if (isset($entry['part']['description'])) {
|
||||
if (!is_string($entry['part']['description']) || trim($entry['part']['description']) === '') {
|
||||
throw new UnexpectedValueException('The property path "part.description" must be a non-empty string if not null');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.string.notEmpty',
|
||||
'entry[$key].part.description',
|
||||
$entry['part']['description']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$partDescription = $entry['part']['description'] ?? '';
|
||||
|
||||
// Part: Manufacturer check
|
||||
|
|
@ -343,7 +440,11 @@ class BOMImporter
|
|||
$manufacturerNameValid = false;
|
||||
if (array_key_exists('manufacturer', $entry['part'])) {
|
||||
if (!is_array($entry['part']['manufacturer'])) {
|
||||
throw new UnexpectedValueException('The property path "part.manufacturer" must be an array');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.array',
|
||||
'entry[$key].part.manufacturer',
|
||||
$entry['part']['manufacturer']) ?? null
|
||||
);
|
||||
}
|
||||
|
||||
$manufacturerIdValid = isset($entry['part']['manufacturer']['id']) && is_int($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] > 0;
|
||||
|
|
@ -351,23 +452,43 @@ class BOMImporter
|
|||
|
||||
// Stellen sicher, dass mindestens eine Bedingung für manufacturer erfüllt sein muss
|
||||
if (!$manufacturerIdValid && !$manufacturerNameValid) {
|
||||
throw new UnexpectedValueException(
|
||||
'The property "manufacturer" must have either assigned: "id" as integer greater than 0, or "name" as non-empty string'
|
||||
);
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties',
|
||||
"entry[$key].part.manufacturer",
|
||||
$entry['part']['manufacturer'],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$manufacturer = $manufacturerIdValid ? $this->manufacturerRepository->findOneBy(['id' => $entry['part']['manufacturer']['id']]) : null;
|
||||
$manufacturer = $manufacturer ?? ($manufacturerNameValid ? $this->manufacturerRepository->findOneBy(['name' => trim($entry['part']['manufacturer']['name'])]) : null);
|
||||
|
||||
if ($manufacturer === null) {
|
||||
throw new RuntimeException(
|
||||
'Manufacturer not found'
|
||||
if (($manufacturerIdValid || $manufacturerNameValid) && $manufacturer === null) {
|
||||
$value = sprintf(
|
||||
'manufacturer.id: %s, manufacturer.name: %s',
|
||||
isset($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] !== null ? '<strong>' . $entry['part']['manufacturer']['id'] . '</strong>' : '-',
|
||||
isset($entry['part']['manufacturer']['name']) && $entry['part']['manufacturer']['name'] !== null ? '<strong>' . $entry['part']['manufacturer']['name'] . '</strong>' : '-'
|
||||
);
|
||||
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.notFoundFor',
|
||||
"entry[$key].part.manufacturer",
|
||||
$entry['part']['manufacturer'],
|
||||
['%value%' => $value]
|
||||
));
|
||||
}
|
||||
|
||||
if ($manufacturerNameValid && $manufacturer->getName() !== trim($entry['part']['manufacturer']['name'])) {
|
||||
throw new RuntimeException(sprintf('Manufacturer name does not match exact the given name. Given for import: %s, found manufacturer: %s', $entry['manufacturer']['name'], $manufacturer->getName()));
|
||||
if ($manufacturerNameValid && $manufacturer !== null && isset($entry['part']['manufacturer']['name']) && $manufacturer->getName() !== trim($entry['part']['manufacturer']['name'])) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.noExactMatch',
|
||||
"entry[$key].part.manufacturer.name",
|
||||
$entry['part']['manufacturer']['name'],
|
||||
[
|
||||
'%importValue%' => '<strong>' . $entry['part']['manufacturer']['name'] . '</strong>',
|
||||
'%foundId%' => $manufacturer->getID(),
|
||||
'%foundValue%' => '<strong>' . $manufacturer->getName() . '</strong>'
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
// Part: Category check
|
||||
|
|
@ -375,49 +496,82 @@ class BOMImporter
|
|||
$categoryNameValid = false;
|
||||
if (array_key_exists('category', $entry['part'])) {
|
||||
if (!is_array($entry['part']['category'])) {
|
||||
throw new UnexpectedValueException('part.category must be an array');
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.array',
|
||||
'entry[$key].part.category',
|
||||
$entry['part']['category']) ?? null
|
||||
);
|
||||
}
|
||||
|
||||
$categoryIdValid = isset($entry['part']['category']['id']) && is_int($entry['part']['category']['id']) && $entry['part']['category']['id'] > 0;
|
||||
$categoryNameValid = isset($entry['part']['category']['name']) && is_string($entry['part']['category']['name']) && trim($entry['part']['category']['name']) !== '';
|
||||
|
||||
if (!$categoryIdValid && !$categoryNameValid) {
|
||||
throw new UnexpectedValueException(
|
||||
'The property "category" must have either assigned: "id" as integer greater than 0, or "name" as non-empty string'
|
||||
);
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties',
|
||||
"entry[$key].part.category",
|
||||
$entry['part']['category']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$category = $categoryIdValid ? $this->categoryRepository->findOneBy(['id' => $entry['part']['category']['id']]) : null;
|
||||
$category = $category ?? ($categoryNameValid ? $this->categoryRepository->findOneBy(['name' => trim($entry['part']['category']['name'])]) : null);
|
||||
|
||||
if ($category === null) {
|
||||
throw new RuntimeException(
|
||||
'Category not found'
|
||||
if (($categoryIdValid || $categoryNameValid) && $category === null) {
|
||||
$value = sprintf(
|
||||
'category.id: %s, category.name: %s',
|
||||
isset($entry['part']['category']['id']) && $entry['part']['category']['id'] !== null ? '<strong>' . $entry['part']['category']['id'] . '</strong>' : '-',
|
||||
isset($entry['part']['category']['name']) && $entry['part']['category']['name'] !== null ? '<strong>' . $entry['part']['category']['name'] . '</strong>' : '-'
|
||||
);
|
||||
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.notFoundFor',
|
||||
"entry[$key].part.category",
|
||||
$entry['part']['category'],
|
||||
['%value%' => $value]
|
||||
));
|
||||
}
|
||||
|
||||
if ($categoryNameValid && $category->getName() !== trim($entry['part']['category']['name'])) {
|
||||
throw new RuntimeException(sprintf('Category name does not match exact the given name. Given for import: %s, found category: %s', $entry['category']['name'], $category->getName()));
|
||||
if ($categoryNameValid && $category !== null && isset($entry['part']['category']['name']) && $category->getName() !== trim($entry['part']['category']['name'])) {
|
||||
$result->addViolation($this->buildJsonViolation(
|
||||
'validator.bom_importer.json.parameter.noExactMatch',
|
||||
"entry[$key].part.category.name",
|
||||
$entry['part']['category']['name'],
|
||||
[
|
||||
'%importValue%' => '<strong>' . $entry['part']['category']['name'] . '</strong>',
|
||||
'%foundId%' => $category->getID(),
|
||||
'%foundValue%' => '<strong>' . $category->getName() . '</strong>'
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
$part->setDescription($partDescription);
|
||||
$part->setManufacturer($manufacturer);
|
||||
$part->setCategory($category);
|
||||
|
||||
if ($partMpnrValid) {
|
||||
$part->setManufacturerProductNumber($entry['part']['mpnr'] ?? '');
|
||||
if ($result->getViolations()->count() > 0) {
|
||||
continue;
|
||||
}
|
||||
if ($partIpnValid) {
|
||||
$part->setIpn($entry['part']['ipn'] ?? '');
|
||||
|
||||
if ($partDescription !== '') {
|
||||
//Beim Import / Aktualisieren von zugehörigen Bauteilen zu einer Baugruppe die Beschreibung des Bauteils mit übernehmen.
|
||||
$part->setDescription($partDescription);
|
||||
}
|
||||
|
||||
if ($manufacturer !== null && $manufacturer->getID() !== $part->getManufacturerID()) {
|
||||
//Beim Import / Aktualisieren von zugehörigen Bauteilen zu einer Baugruppe des Hersteller des Bauteils mit übernehmen.
|
||||
$part->setManufacturer($manufacturer);
|
||||
}
|
||||
|
||||
if ($category !== null && $category->getID() !== $part->getCategoryID()) {
|
||||
//Beim Import / Aktualisieren von zugehörigen Bauteilen zu einer Baugruppe die Kategorie des Bauteils mit übernehmen.
|
||||
$part->setCategory($category);
|
||||
}
|
||||
|
||||
if ($objectType === AssemblyBOMEntry::class) {
|
||||
$bomEntry = $this->assemblyBOMEntryRepository->findOneBy(['part' => $part]);
|
||||
|
||||
if ($bomEntry === null) {
|
||||
$name = isset($entry['name']) && $entry['name'] !== null ? trim($entry['name']) : '';
|
||||
$bomEntry = $this->assemblyBOMEntryRepository->findOneBy(['name' => $name]);
|
||||
if (isset($entry['name']) && $entry['name'] !== '') {
|
||||
$bomEntry = $this->assemblyBOMEntryRepository->findOneBy(['name' => $entry['name']]);
|
||||
}
|
||||
|
||||
if ($bomEntry === null) {
|
||||
$bomEntry = new AssemblyBOMEntry();
|
||||
|
|
@ -431,9 +585,22 @@ class BOMImporter
|
|||
$bomEntry->setName($entry['name'] ?? '');
|
||||
|
||||
$bomEntry->setPart($part);
|
||||
}
|
||||
|
||||
$result[] = $bomEntry;
|
||||
$result->addBomEntry($bomEntry);
|
||||
} else {
|
||||
//Eintrag ohne Part-Relation in die Bauteilliste aufnehmen
|
||||
|
||||
if ($objectType === AssemblyBOMEntry::class) {
|
||||
$bomEntry = new AssemblyBOMEntry();
|
||||
} else {
|
||||
$bomEntry = new ProjectBOMEntry();
|
||||
}
|
||||
|
||||
$bomEntry->setQuantity($entry['quantity']);
|
||||
$bomEntry->setName($entry['name'] ?? '');
|
||||
|
||||
$result->addBomEntry($bomEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
|
@ -462,6 +629,18 @@ class BOMImporter
|
|||
return $out;
|
||||
}
|
||||
|
||||
private function buildJsonViolation(string $message, string $propertyPath, mixed $invalidValue = null, array $parameters = []): ConstraintViolation
|
||||
{
|
||||
return new ConstraintViolation(
|
||||
message: $this->translator->trans($message, $parameters, 'validators'),
|
||||
messageTemplate: $message,
|
||||
parameters: $parameters,
|
||||
root: $this->jsonRoot,
|
||||
propertyPath: $propertyPath,
|
||||
invalidValue: $invalidValue
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse KiCad schematic BOM with flexible field mapping
|
||||
*/
|
||||
|
|
|
|||
60
src/Services/ImportExportSystem/ImporterResult.php
Normal file
60
src/Services/ImportExportSystem/ImporterResult.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ImportExportSystem;
|
||||
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
|
||||
class ImporterResult
|
||||
{
|
||||
private array $bomEntries = [];
|
||||
private ConstraintViolationList $violations;
|
||||
|
||||
public function __construct(array $bomEntries = [])
|
||||
{
|
||||
$this->bomEntries = $bomEntries;
|
||||
$this->violations = new ConstraintViolationList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt einen neuen BOM-Eintrag hinzu.
|
||||
*/
|
||||
public function addBomEntry(object $bomEntry): void
|
||||
{
|
||||
$this->bomEntries[] = $bomEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt alle BOM-Einträge zurück.
|
||||
*/
|
||||
public function getBomEntries(): array
|
||||
{
|
||||
return $this->bomEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Liste der Violation zurück.
|
||||
*/
|
||||
public function getViolations(): ConstraintViolationList
|
||||
{
|
||||
return $this->violations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt eine neue `ConstraintViolation` zur Liste hinzu.
|
||||
*/
|
||||
public function addViolation(ConstraintViolation $violation): void
|
||||
{
|
||||
$this->violations->add($violation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob die Liste der Violationen leer ist.
|
||||
*/
|
||||
public function hasViolations(): bool
|
||||
{
|
||||
return count($this->violations) > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,16 +3,27 @@
|
|||
{% block title %}{% trans %}assembly.import_bom{% endtrans %}{% endblock %}
|
||||
|
||||
{% block before_card %}
|
||||
{% if errors %}
|
||||
{% if validationErrors or importerErrors %}
|
||||
<div class="alert alert-danger">
|
||||
<h4><i class="fa-solid fa-exclamation-triangle fa-fw"></i> {% trans %}parts.import.errors.title{% endtrans %}</h4>
|
||||
<ul>
|
||||
{% for violation in errors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators') }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if validationErrors %}
|
||||
{% for violation in validationErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators') }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if importerErrors %}
|
||||
{% for violation in importerErrors %}
|
||||
<li>
|
||||
<b>{{ violation.propertyPath }}: </b>
|
||||
{{ violation.message|trans(violation.parameters, 'validators')|raw }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -389,5 +389,59 @@
|
|||
<target>Musíte vybrat součást nebo nastavit název pro nesoučást!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Musíte zadat množství > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>očekává se jako float větší než 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>očekává se jako neprázdný řetězec</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>očekává se jako neprázdný řetězec nebo null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>očekává se jako pole (array)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>musí mít alespoň jeden z následujících pod-parametrů: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>nenalezeno pro %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>se přesně neshoduje. Pro import zadáno: %importValue%, nalezeno (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>musí obsahovat jako pod-parametr buď: "id" jako celé číslo větší než 0 nebo "name" jako neprázdný řetězec</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -365,5 +365,59 @@
|
|||
<target>Du skal vælge en del eller sætte et navn for en ikke-del!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Du skal angive en mængde > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>forventet som en float større end 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>forventet som en ikke-tom streng</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>forventet som en ikke-tom streng eller null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>forventet som en array</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>skal have mindst én af følgende underparametre: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>ikke fundet for %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>stemmer ikke helt overens. Givet til import: %importValue%, fundet (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>skal indeholde som en underparameter enten: "id" som et heltal større end 0 eller "name" som en ikke-tom streng</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -386,7 +386,61 @@
|
|||
<unit id="KWc.wZ4" name="validator.assembly.bom_entry.name_or_part_needed">
|
||||
<segment>
|
||||
<source>validator.assembly.bom_entry.name_or_part_needed</source>
|
||||
<target>Sie müssen ein Bauteil auswählen, oder einen Namen für ein nicht-Bauteil setzen!</target>
|
||||
<target>Sie müssen ein Bauteil auswählen, oder einen Namen für den Eintrag setzen!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Sie müssen eine Stückzahl > 0 angeben!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>wird als float größer als 0.0 erwartet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>als nicht leere Zeichenkette erwartet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>als nicht leere Zeichenkette oder null erwartet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>als array erwartet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>muss mindestens eines der folgenden Unter-Parameter haben: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>nicht gefunden für %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>stimmt nicht genau überein. Für den Import gegeben: %importValue%, gefunden (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>muss entweder als Unter-Parameter zugewiesen haben: "id" als Ganzzahl größer als 0 oder "name" als nicht leere Zeichenfolge</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
|
|
|
|||
|
|
@ -31,5 +31,59 @@
|
|||
<target>Πρέπει να επιλέξετε ένα εξάρτημα ή να βάλετε ένα όνομα για ένα μη εξάρτημα!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Πρέπει να εισαγάγετε ποσότητα > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>αναμένεται ως δεκαδικός αριθμός (float) μεγαλύτερος από 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>αναμένεται ως μη κενή συμβολοσειρά</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>αναμένεται ως μη κενή συμβολοσειρά ή null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>αναμένεται ως array</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>πρέπει να έχει τουλάχιστον μία από τις ακόλουθες υπο-παραμέτρους: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>δεν βρέθηκε για %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>δεν ταιριάζει απόλυτα. Δόθηκε για εισαγωγή: %importValue%, βρέθηκε (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>πρέπει να περιέχει ως υπο-παράμετρο είτε: "id" ως ακέραιο αριθμό μεγαλύτερο από 0 είτε "name" ως μη κενή συμβολοσειρά</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -389,5 +389,59 @@
|
|||
<target>__validator.assembly.bom_entry.name_or_part_needed</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>you must specify a quantity > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>expected as float greater than 0.0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>expected as non-empty string</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>als nicht leere Zeichenkette oder null erwartet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>expectd as array</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>must have at least one of the following sub-properties: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>not found for %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>does not match exactly. Given for import: %importValue%, found (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>must have either assigned as sub-property: "id" as an integer greater than 0, or "name" as a non-empty string</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -224,7 +224,61 @@
|
|||
<unit id="KWc.wZ4" name="validator.assembly.bom_entry.name_or_part_needed">
|
||||
<segment>
|
||||
<source>validator.assembly.bom_entry.name_or_part_needed</source>
|
||||
<target>Vous devez sélectionner une pièce ou attribuer un nom pour un non-élément !</target>
|
||||
<target>Vous devez sélectionner une pièce ou attribuer un nom pour un non-élément!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Vous devez entrer une quantité > 0 !</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>attendu comme un nombre décimal (float) supérieur à 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>attendu comme une chaîne de caractères non vide</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>attendu comme une chaîne de caractères non vide ou null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>attendu comme un tableau (array)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>doit contenir au moins l'un des sous-paramètres suivants : %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>non trouvé pour %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>ne correspond pas exactement. Donné pour l'importation : %importValue%, trouvé (%foundId%) : %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>doit contenir comme sous-paramètre soit : "id" comme entier supérieur à 0 ou "name" comme chaîne de caractères non vide</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
|
|
|
|||
|
|
@ -383,5 +383,59 @@
|
|||
<target>Morate odabrati dio ili unijeti naziv za nedio!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Morate unijeti količinu > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>očekuje se decimalni broj (float) veći od 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>očekuje se kao neprazan niz znakova</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>očekuje se kao neprazan niz znakova ili null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>očekuje se kao niz</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>mora sadržavati barem jedan od sljedećih pod-parametara: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>nije pronađeno za %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>ne podudara se točno. Uneseno za uvoz: %importValue%, pronađeno (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>mora sadržavati kao pod-parametar bilo: "id" kao cijeli broj veći od 0 ili "name" kao neprazan niz znakova</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -383,5 +383,59 @@
|
|||
<target>È necessario selezionare una parte o inserire un nome per un non-parte!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Devi inserire una quantità > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>atteso come numero decimale (float) maggiore di 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>atteso come stringa non vuota</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>atteso come stringa non vuota o null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>atteso come array</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>deve avere almeno uno dei seguenti sotto-parametri: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>non trovato per %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>non corrisponde esattamente. Valore dato per l'importazione: %importValue%, trovato (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>deve contenere come sotto-parametro: "id" come intero maggiore di 0 o "name" come stringa non vuota</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -227,5 +227,59 @@
|
|||
<target>部品を選択するか、非部品の名前を入力する必要があります!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>数量 > 0 を入力する必要があります!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>0.0 より大きい小数 (float) である必要があります</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>空でない文字列が期待されます</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>空でない文字列または null が期待されます</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>配列として期待されます</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>以下のサブパラメーターのいずれかを含む必要があります:%propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>%value% に対する項目が見つかりません</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>完全には一致しません。インポートされた値:%importValue%、見つかった値 (%foundId%):%foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>サブパラメーターとして次のいずれかを含む必要があります:"id" は 0 より大きい整数、または "name" は空でない文字列</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -383,5 +383,59 @@
|
|||
<target>Musisz wybrać element lub przypisać nazwę dla elementu niestandardowego!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Musisz wprowadzić ilość > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>oczekiwano liczby zmiennoprzecinkowej (float) większej od 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>oczekiwano jako niepusty ciąg znaków</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>oczekiwano jako niepusty ciąg znaków lub null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>oczekiwano jako tablicę</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>musi zawierać co najmniej jeden z następujących podparametrów: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>nie znaleziono dla %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>brak dokładnego dopasowania. Wprowadzone do importu: %importValue%, znalezione (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>musi zawierać jako podparametr: "id" jako liczbę całkowitą większą od 0 lub "name" jako niepusty ciąg znaków</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -383,5 +383,59 @@
|
|||
<target>Необходимо выбрать деталь или ввести название для недетали!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>Необходимо указать количество > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>ожидается число с плавающей запятой (float), большее 0,0</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>ожидается непустая строка</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>ожидается непустая строка или null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>ожидается массив</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>должен содержать хотя бы один из следующих под-параметров: %propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>не найдено для %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>точное совпадение отсутствует. Указано для импорта: %importValue%, найдено (%foundId%): %foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>должен содержать под-параметр: "id" как целое число больше 0 или "name" как непустая строка</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -371,5 +371,59 @@
|
|||
<target>必须选择零件或为非零件指定名称!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="a1dKro7" name="validator.bom_importer.json.quantity.required">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.required</source>
|
||||
<target>必须输入数量 > 0!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hlBA1Pd" name="validator.bom_importer.json.quantity.float">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.quantity.float</source>
|
||||
<target>应为大于 0.0 的浮点数 (float)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eBCiG.1" name="validator.bom_importer.json.parameter.string.notEmpty">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty</source>
|
||||
<target>应为非空字符串</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aKg7qlT" name="validator.bom_importer.json.parameter.string.notEmpty.null">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.string.notEmpty.null</source>
|
||||
<target>应为非空字符串或 null</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="g8HPqwx" name="validator.bom_importer.json.parameter.array">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.array</source>
|
||||
<target>应为数组</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="adLRxnA" name="validator.bom_importer.json.parameter.subproperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.subproperties</source>
|
||||
<target>必须包含以下子参数之一:%propertyString%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kt12PW4" name="validator.bom_importer.json.parameter.notFoundFor">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.notFoundFor</source>
|
||||
<target>未找到对应值 %value%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bhc3WQf" name="validator.bom_importer.json.parameter.noExactMatch">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.noExactMatch</source>
|
||||
<target>未精确匹配。用于导入的值:%importValue%,找到的值 (%foundId%):%foundValue%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Kb1hpq3" name="validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties">
|
||||
<segment>
|
||||
<source>validator.bom_importer.json.parameter.manufacturerOrCategoryWithSubProperties</source>
|
||||
<target>必须包含子参数:"id" 为大于 0 的整数,或 "name" 为非空字符串</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue