mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-08-14 15:08:47 +02:00
Allow to use arrow style full-paths for mass creation of entities
Some checks are pending
Build assets artifact / Build assets artifact (push) Waiting to run
Docker Image Build / docker (push) Waiting to run
Docker Image Build (FrankenPHP) / docker (push) Waiting to run
Static analysis / Static analysis (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Waiting to run
Some checks are pending
Build assets artifact / Build assets artifact (push) Waiting to run
Docker Image Build / docker (push) Waiting to run
Docker Image Build (FrankenPHP) / docker (push) Waiting to run
Static analysis / Static analysis (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.1, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Waiting to run
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Waiting to run
This fixes issue #993
This commit is contained in:
parent
23cd51c1ca
commit
128b428644
3 changed files with 89 additions and 57 deletions
|
@ -57,6 +57,7 @@ class EntityImporter
|
|||
/**
|
||||
* Creates many entries at once, based on a (text) list of name.
|
||||
* The created entities are not persisted to database yet, so you have to do it yourself.
|
||||
* It returns all entities in the hierachy chain (even if they are already persisted).
|
||||
*
|
||||
* @template T of AbstractNamedDBElement
|
||||
* @param string $lines The list of names seperated by \n
|
||||
|
@ -132,32 +133,35 @@ class EntityImporter
|
|||
//We can only use the getNewEntityFromPath function, if the repository is a StructuralDBElementRepository
|
||||
if ($repo instanceof StructuralDBElementRepository) {
|
||||
$entities = $repo->getNewEntityFromPath($new_path);
|
||||
$entity = end($entities);
|
||||
if ($entity === false) {
|
||||
if ($entities === []) {
|
||||
throw new InvalidArgumentException('getNewEntityFromPath returned an empty array!');
|
||||
}
|
||||
} else { //Otherwise just create a new entity
|
||||
$entity = new $class_name;
|
||||
$entity->setName($name);
|
||||
$entities = [$entity];
|
||||
}
|
||||
|
||||
|
||||
//Validate entity
|
||||
$tmp = $this->validator->validate($entity);
|
||||
//If no error occured, write entry to DB:
|
||||
if (0 === count($tmp)) {
|
||||
$valid_entities[] = $entity;
|
||||
} else { //Otherwise log error
|
||||
$errors[] = [
|
||||
'entity' => $entity,
|
||||
'violations' => $tmp,
|
||||
];
|
||||
foreach ($entities as $entity) {
|
||||
$tmp = $this->validator->validate($entity);
|
||||
//If no error occured, write entry to DB:
|
||||
if (0 === count($tmp)) {
|
||||
$valid_entities[] = $entity;
|
||||
} else { //Otherwise log error
|
||||
$errors[] = [
|
||||
'entity' => $entity,
|
||||
'violations' => $tmp,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$last_element = $entity;
|
||||
}
|
||||
|
||||
return $valid_entities;
|
||||
//Only return objects once
|
||||
return array_values(array_unique($valid_entities));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,8 +75,8 @@ class EntityImporterTest extends WebTestCase
|
|||
$em = self::getContainer()->get(EntityManagerInterface::class);
|
||||
$parent = $em->find(AttachmentType::class, 1);
|
||||
$results = $this->service->massCreation($lines, AttachmentType::class, $parent, $errors);
|
||||
$this->assertCount(3, $results);
|
||||
$this->assertSame($parent, $results[0]->getParent());
|
||||
$this->assertCount(4, $results);
|
||||
$this->assertSame("Test 1", $results[1]->getName());
|
||||
|
||||
//Test for addition of existing elements
|
||||
$errors = [];
|
||||
|
@ -113,6 +113,31 @@ EOT;
|
|||
|
||||
}
|
||||
|
||||
public function testMassCreationArrow(): void
|
||||
{
|
||||
$input = <<<EOT
|
||||
Test1 -> Test1.1
|
||||
Test1 -> Test1.2
|
||||
Test2 -> Test2.1
|
||||
Test1
|
||||
Test1.3
|
||||
EOT;
|
||||
|
||||
$errors = [];
|
||||
$results = $this->service->massCreation($input, AttachmentType::class, null, $errors);
|
||||
|
||||
//We have 6 elements, and 0 errors
|
||||
$this->assertCount(0, $errors);
|
||||
$this->assertCount(6, $results);
|
||||
|
||||
$this->assertEquals('Test1', $results[0]->getName());
|
||||
$this->assertEquals('Test1.1', $results[1]->getName());
|
||||
$this->assertEquals('Test1.2', $results[2]->getName());
|
||||
$this->assertEquals('Test2', $results[3]->getName());
|
||||
$this->assertEquals('Test2.1', $results[4]->getName());
|
||||
$this->assertEquals('Test1.3', $results[5]->getName());
|
||||
}
|
||||
|
||||
public function testMassCreationNested(): void
|
||||
{
|
||||
$input = <<<EOT
|
||||
|
@ -132,15 +157,15 @@ EOT;
|
|||
|
||||
//We have 7 elements, and 0 errors
|
||||
$this->assertCount(0, $errors);
|
||||
$this->assertCount(7, $results);
|
||||
$this->assertCount(8, $results);
|
||||
|
||||
$element1 = $results[0];
|
||||
$element11 = $results[1];
|
||||
$element111 = $results[2];
|
||||
$element112 = $results[3];
|
||||
$element12 = $results[4];
|
||||
$element121 = $results[5];
|
||||
$element2 = $results[6];
|
||||
$element1 = $results[1];
|
||||
$element11 = $results[2];
|
||||
$element111 = $results[3];
|
||||
$element112 = $results[4];
|
||||
$element12 = $results[5];
|
||||
$element121 = $results[6];
|
||||
$element2 = $results[7];
|
||||
|
||||
$this->assertSame('Test 1', $element1->getName());
|
||||
$this->assertSame('Test 1.1', $element11->getName());
|
||||
|
|
|
@ -242,7 +242,7 @@
|
|||
</notes>
|
||||
<segment state="final">
|
||||
<source>part.info.timetravel_hint</source>
|
||||
<target>This is how the part appeared before %timestamp%. <i>Please note that this feature is experimental, so the info may not be correct.</i></target>
|
||||
<target><![CDATA[This is how the part appeared before %timestamp%. <i>Please note that this feature is experimental, so the info may not be correct.</i>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3exvSpl" name="standard.label">
|
||||
|
@ -731,10 +731,10 @@
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>user.edit.tfa.disable_tfa_message</source>
|
||||
<target>This will disable <b>all active two-factor authentication methods of the user</b> and delete the <b>backup codes</b>!
|
||||
<br>
|
||||
The user will have to set up all two-factor authentication methods again and print new backup codes! <br><br>
|
||||
<b>Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!</b></target>
|
||||
<target><![CDATA[This will disable <b>all active two-factor authentication methods of the user</b> and delete the <b>backup codes</b>!
|
||||
<br>
|
||||
The user will have to set up all two-factor authentication methods again and print new backup codes! <br><br>
|
||||
<b>Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!</b>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="APsHYu0" name="user.edit.tfa.disable_tfa.btn">
|
||||
|
@ -885,9 +885,9 @@ The user will have to set up all two-factor authentication methods again and pri
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>entity.delete.message</source>
|
||||
<target>This can not be undone!
|
||||
<br>
|
||||
Sub elements will be moved upwards.</target>
|
||||
<target><![CDATA[This can not be undone!
|
||||
<br>
|
||||
Sub elements will be moved upwards.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2tKAqHw" name="entity.delete">
|
||||
|
@ -1441,7 +1441,7 @@ Sub elements will be moved upwards.</target>
|
|||
</notes>
|
||||
<segment state="final">
|
||||
<source>homepage.github.text</source>
|
||||
<target>Source, downloads, bug reports, to-do-list etc. can be found on <a href="%href%" class="link-external" target="_blank">GitHub project page</a></target>
|
||||
<target><![CDATA[Source, downloads, bug reports, to-do-list etc. can be found on <a href="%href%" class="link-external" target="_blank">GitHub project page</a>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="D5OKsgU" name="homepage.help.caption">
|
||||
|
@ -1463,7 +1463,7 @@ Sub elements will be moved upwards.</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>homepage.help.text</source>
|
||||
<target>Help and tips can be found in Wiki the <a href="%href%" class="link-external" target="_blank">GitHub page</a></target>
|
||||
<target><![CDATA[Help and tips can be found in Wiki the <a href="%href%" class="link-external" target="_blank">GitHub page</a>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="dnirx4v" name="homepage.forum.caption">
|
||||
|
@ -1705,7 +1705,7 @@ Sub elements will be moved upwards.</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>email.pw_reset.fallback</source>
|
||||
<target>If this does not work for you, go to <a href="%url%">%url%</a> and enter the following info</target>
|
||||
<target><![CDATA[If this does not work for you, go to <a href="%url%">%url%</a> and enter the following info]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="DduL9Hu" name="email.pw_reset.username">
|
||||
|
@ -1735,7 +1735,7 @@ Sub elements will be moved upwards.</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>email.pw_reset.valid_unit %date%</source>
|
||||
<target>The reset token will be valid until <i>%date%</i>.</target>
|
||||
<target><![CDATA[The reset token will be valid until <i>%date%</i>.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8sBnjRy" name="orderdetail.delete">
|
||||
|
@ -3578,8 +3578,8 @@ Sub elements will be moved upwards.</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>tfa_google.disable.confirm_message</source>
|
||||
<target>If you disable the Authenticator App, all backup codes will be deleted, so you may need to reprint them.<br>
|
||||
Also note that without two-factor authentication, your account is no longer as well protected against attackers!</target>
|
||||
<target><![CDATA[If you disable the Authenticator App, all backup codes will be deleted, so you may need to reprint them.<br>
|
||||
Also note that without two-factor authentication, your account is no longer as well protected against attackers!]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="yu9MSt5" name="tfa_google.disabled_message">
|
||||
|
@ -3599,7 +3599,7 @@ Also note that without two-factor authentication, your account is no longer as w
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>tfa_google.step.download</source>
|
||||
<target>Download an authenticator app (e.g. <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a> oder <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp">FreeOTP Authenticator</a>)</target>
|
||||
<target><![CDATA[Download an authenticator app (e.g. <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a> oder <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp">FreeOTP Authenticator</a>)]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eriwJoR" name="tfa_google.step.scan">
|
||||
|
@ -3841,8 +3841,8 @@ Also note that without two-factor authentication, your account is no longer as w
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>tfa_trustedDevices.explanation</source>
|
||||
<target>When checking the second factor, the current computer can be marked as trustworthy, so no more two-factor checks on this computer are needed.
|
||||
If you have done this incorrectly or if a computer is no longer trusted, you can reset the status of <i>all </i>computers here.</target>
|
||||
<target><![CDATA[When checking the second factor, the current computer can be marked as trustworthy, so no more two-factor checks on this computer are needed.
|
||||
If you have done this incorrectly or if a computer is no longer trusted, you can reset the status of <i>all </i>computers here.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="FZINq8z" name="tfa_trustedDevices.invalidate.confirm_title">
|
||||
|
@ -5313,7 +5313,7 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>label_options.lines_mode.help</source>
|
||||
<target>If you select Twig here, the content field is interpreted as Twig template. See <a href="https://twig.symfony.com/doc/3.x/templates.html">Twig documentation</a> and <a href="https://docs.part-db.de/usage/labels.html#twig-mode">Wiki</a> for more information.</target>
|
||||
<target><![CDATA[If you select Twig here, the content field is interpreted as Twig template. See <a href="https://twig.symfony.com/doc/3.x/templates.html">Twig documentation</a> and <a href="https://docs.part-db.de/usage/labels.html#twig-mode">Wiki</a> for more information.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="isvxbiX" name="label_options.page_size.label">
|
||||
|
@ -7157,12 +7157,15 @@ Exampletown</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>mass_creation.lines.placeholder</source>
|
||||
<target>Element 1
|
||||
<target><![CDATA[Element 1
|
||||
Element 1.1
|
||||
Element 1.1.1
|
||||
Element 1.2
|
||||
Element 2
|
||||
Element 3</target>
|
||||
Element 3
|
||||
|
||||
Element 1 -> Element 1.1
|
||||
Element 1 -> Element 1.2]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="TWSqPFi" name="entity.mass_creation.btn">
|
||||
|
@ -9388,25 +9391,25 @@ Element 3</target>
|
|||
<unit id="r4vDLAt" name="filter.parameter_value_constraint.operator.<">
|
||||
<segment state="translated">
|
||||
<source>filter.parameter_value_constraint.operator.<</source>
|
||||
<target>Typ. Value <</target>
|
||||
<target><![CDATA[Typ. Value <]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="X9SA3UP" name="filter.parameter_value_constraint.operator.>">
|
||||
<segment state="translated">
|
||||
<source>filter.parameter_value_constraint.operator.></source>
|
||||
<target>Typ. Value ></target>
|
||||
<target><![CDATA[Typ. Value >]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BQGaoQS" name="filter.parameter_value_constraint.operator.<=">
|
||||
<segment state="translated">
|
||||
<source>filter.parameter_value_constraint.operator.<=</source>
|
||||
<target>Typ. Value <=</target>
|
||||
<target><![CDATA[Typ. Value <=]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2ha3P6g" name="filter.parameter_value_constraint.operator.>=">
|
||||
<segment state="translated">
|
||||
<source>filter.parameter_value_constraint.operator.>=</source>
|
||||
<target>Typ. Value >=</target>
|
||||
<target><![CDATA[Typ. Value >=]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4DaBace" name="filter.parameter_value_constraint.operator.BETWEEN">
|
||||
|
@ -9514,7 +9517,7 @@ Element 3</target>
|
|||
<unit id="4tHhDtU" name="parts_list.search.searching_for">
|
||||
<segment state="translated">
|
||||
<source>parts_list.search.searching_for</source>
|
||||
<target>Searching parts with keyword <b>%keyword%</b></target>
|
||||
<target><![CDATA[Searching parts with keyword <b>%keyword%</b>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4vomKLa" name="parts_list.search_options.caption">
|
||||
|
@ -10174,13 +10177,13 @@ Element 3</target>
|
|||
<unit id="NdZ1t7a" name="project.builds.number_of_builds_possible">
|
||||
<segment state="translated">
|
||||
<source>project.builds.number_of_builds_possible</source>
|
||||
<target>You have enough stocked to build <b>%max_builds%</b> builds of this project.</target>
|
||||
<target><![CDATA[You have enough stocked to build <b>%max_builds%</b> builds of this project.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iuSpPbg" name="project.builds.check_project_status">
|
||||
<segment state="translated">
|
||||
<source>project.builds.check_project_status</source>
|
||||
<target>The current project status is <b>"%project_status%"</b>. You should check if you really want to build the project with this status!</target>
|
||||
<target><![CDATA[The current project status is <b>"%project_status%"</b>. You should check if you really want to build the project with this status!]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Y7vSSxi" name="project.builds.following_bom_entries_miss_instock_n">
|
||||
|
@ -10282,7 +10285,7 @@ Element 3</target>
|
|||
<unit id="GzqIwHH" name="entity.select.add_hint">
|
||||
<segment state="translated">
|
||||
<source>entity.select.add_hint</source>
|
||||
<target>Use -> to create nested structures, e.g. "Node 1->Node 1.1"</target>
|
||||
<target><![CDATA[Use -> to create nested structures, e.g. "Node 1->Node 1.1"]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="S4CxO.T" name="entity.select.group.new_not_added_to_DB">
|
||||
|
@ -10306,13 +10309,13 @@ Element 3</target>
|
|||
<unit id="XLnXtsR" name="homepage.first_steps.introduction">
|
||||
<segment state="translated">
|
||||
<source>homepage.first_steps.introduction</source>
|
||||
<target>Your database is still empty. You might want to read the <a href="%url%">documentation</a> or start to creating the following data structures:</target>
|
||||
<target><![CDATA[Your database is still empty. You might want to read the <a href="%url%">documentation</a> or start to creating the following data structures:]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Q79MOIk" name="homepage.first_steps.create_part">
|
||||
<segment state="translated">
|
||||
<source>homepage.first_steps.create_part</source>
|
||||
<target>Or you can directly <a href="%url%">create a new part</a>.</target>
|
||||
<target><![CDATA[Or you can directly <a href="%url%">create a new part</a>.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="vplYq4f" name="homepage.first_steps.hide_hint">
|
||||
|
@ -10324,7 +10327,7 @@ Element 3</target>
|
|||
<unit id="MJoZl4f" name="homepage.forum.text">
|
||||
<segment state="translated">
|
||||
<source>homepage.forum.text</source>
|
||||
<target>For questions about Part-DB use the <a href="%href%" class="link-external" target="_blank">discussion forum</a></target>
|
||||
<target><![CDATA[For questions about Part-DB use the <a href="%href%" class="link-external" target="_blank">discussion forum</a>]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="YsukbnK" name="log.element_edited.changed_fields.category">
|
||||
|
@ -10978,7 +10981,7 @@ Element 3</target>
|
|||
<unit id="p_IxB9K" name="parts.import.help_documentation">
|
||||
<segment state="translated">
|
||||
<source>parts.import.help_documentation</source>
|
||||
<target>See the <a href="%link%">documentation</a> for more information on the file format.</target>
|
||||
<target><![CDATA[See the <a href="%link%">documentation</a> for more information on the file format.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="awbvhVq" name="parts.import.help">
|
||||
|
@ -11158,7 +11161,7 @@ Element 3</target>
|
|||
<unit id="o5u.Nnz" name="part.filter.lessThanDesired">
|
||||
<segment state="translated">
|
||||
<source>part.filter.lessThanDesired</source>
|
||||
<target>In stock less than desired (total amount < min. amount)</target>
|
||||
<target><![CDATA[In stock less than desired (total amount < min. amount)]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="YN9eLcZ" name="part.filter.lotOwner">
|
||||
|
@ -11970,13 +11973,13 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
|||
<unit id="i68lU5x" name="part.merge.confirm.title">
|
||||
<segment state="translated">
|
||||
<source>part.merge.confirm.title</source>
|
||||
<target>Do you really want to merge <b>%other%</b> into <b>%target%</b>?</target>
|
||||
<target><![CDATA[Do you really want to merge <b>%other%</b> into <b>%target%</b>?]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="k0anzYV" name="part.merge.confirm.message">
|
||||
<segment state="translated">
|
||||
<source>part.merge.confirm.message</source>
|
||||
<target><b>%other%</b> will be deleted, and the part will be saved with the shown information.</target>
|
||||
<target><![CDATA[<b>%other%</b> will be deleted, and the part will be saved with the shown information.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="mmW5Yl1" name="part.info.merge_modal.title">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue