]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make `RandomMetadata` properly support localization (#36343)
authorTayrtahn <tayrtahn@gmail.com>
Sun, 6 Apr 2025 18:12:39 +0000 (14:12 -0400)
committerGitHub <noreply@github.com>
Sun, 6 Apr 2025 18:12:39 +0000 (11:12 -0700)
* Make _outputSegments readonly

* Remove mystery character

* Use Fluent instead of string concatenation

* Adjust format

* Convert existing content

* Don't need these anymore

* Docs

17 files changed:
Content.Server/RandomMetadata/RandomMetadataComponent.cs
Content.Server/RandomMetadata/RandomMetadataSystem.cs
Resources/Locale/en-US/datasets/names/joining.ftl [deleted file]
Resources/Locale/en-US/datasets/names/nukie_first.ftl [deleted file]
Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl [new file with mode: 0644]
Resources/Prototypes/Datasets/Names/joining.yml [deleted file]
Resources/Prototypes/Datasets/Names/nukies.yml [deleted file]
Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml
Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml
Resources/Prototypes/Entities/Mobs/Player/ShuttleRoles/settings.yml
Resources/Prototypes/Entities/Mobs/Player/human.yml
Resources/Prototypes/Entities/Mobs/Player/humanoid.yml
Resources/Prototypes/Entities/Objects/Misc/books.yml
Resources/Prototypes/Entities/Objects/Tools/decoys.yml
Resources/Prototypes/GameRules/events.yml
Resources/Prototypes/GameRules/roundstart.yml
Resources/Prototypes/GameRules/subgamemodes.yml

index 24d07f427721cd35618f8598d28d5b8548cfec8b..d454ec29f51afef6864e287871a4eebe57172416 100644 (file)
@@ -1,7 +1,7 @@
 using Content.Shared.Dataset;
 using Robust.Shared.Prototypes;
 
-namespace Content.Server.RandomMetadata;
+namespace Content.Server.RandomMetadata;
 
 /// <summary>
 ///     Randomizes the description and/or the name for an entity by creating it from list of dataset prototypes or strings.
@@ -15,9 +15,17 @@ public sealed partial class RandomMetadataComponent : Component
     [DataField]
     public List<ProtoId<LocalizedDatasetPrototype>>? NameSegments;
 
+    /// <summary>
+    /// LocId of the formatting string to use to assemble the <see cref="NameSegments"/> into the entity's name.
+    /// Segments will be passed to the localization system with this string as variables named $part0, $part1, $part2, etc.
+    /// </summary>
     [DataField]
-    public string NameSeparator = " ";
+    public LocId NameFormat = "random-metadata-name-format-default";
 
+    /// <summary>
+    /// LocId of the formatting string to use to assemble the <see cref="DescriptionSegments"/> into the entity's description.
+    /// Segments will be passed to the localization system with this string as variables named $part0, $part1, $part2, etc.
+    /// </summary>
     [DataField]
-    public string DescriptionSeparator = " ";
+    public LocId DescriptionFormat = "random-metadata-description-format-default";
 }
index 2127f825e94191a765d8cab456c56c948fa9733d..db6f8833f3966b2a0963479d6e89b7fe4ca3cf8d 100644 (file)
@@ -12,7 +12,7 @@ public sealed class RandomMetadataSystem : EntitySystem
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly MetaDataSystem _metaData = default!;
 
-    private List<string> _outputSegments = new();
+    private readonly List<(string, object)> _outputSegments = new();
 
     public override void Initialize()
     {
@@ -28,13 +28,13 @@ public sealed class RandomMetadataSystem : EntitySystem
 
         if (component.NameSegments != null)
         {
-            _metaData.SetEntityName(uid, GetRandomFromSegments(component.NameSegments, component.NameSeparator), meta);
+            _metaData.SetEntityName(uid, GetRandomFromSegments(component.NameSegments, component.NameFormat), meta);
         }
 
         if (component.DescriptionSegments != null)
         {
             _metaData.SetEntityDescription(uid,
-                GetRandomFromSegments(component.DescriptionSegments, component.DescriptionSeparator), meta);
+                GetRandomFromSegments(component.DescriptionSegments, component.DescriptionFormat), meta);
         }
     }
 
@@ -42,17 +42,18 @@ public sealed class RandomMetadataSystem : EntitySystem
     /// Generates a random string from segments and a separator.
     /// </summary>
     /// <param name="segments">The segments that it will be generated from</param>
-    /// <param name="separator">The separator that will be inbetween each segment</param>
+    /// <param name="format">The format string used to combine the segments.</param>
     /// <returns>The newly generated string</returns>
     [PublicAPI]
-    public string GetRandomFromSegments(List<ProtoId<LocalizedDatasetPrototype>> segments, string? separator)
+    public string GetRandomFromSegments(List<ProtoId<LocalizedDatasetPrototype>> segments, LocId format)
     {
         _outputSegments.Clear();
-        foreach (var segment in segments)
+        for (var i = 0; i < segments.Count; ++i)
         {
-            var localizedProto = _prototype.Index(segment);
-            _outputSegments.Add(_random.Pick(localizedProto));
+            var localizedProto = _prototype.Index(segments[i]);
+            _outputSegments.Add(($"part{i}", _random.Pick(localizedProto)));
         }
-        return string.Join(separator, _outputSegments);
+
+        return Loc.GetString(format, _outputSegments.ToArray());
     }
 }
diff --git a/Resources/Locale/en-US/datasets/names/joining.ftl b/Resources/Locale/en-US/datasets/names/joining.ftl
deleted file mode 100644 (file)
index 3baeb89..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-names-word-the-1 = The
-names-word-of-1 = of
diff --git a/Resources/Locale/en-US/datasets/names/nukie_first.ftl b/Resources/Locale/en-US/datasets/names/nukie_first.ftl
deleted file mode 100644 (file)
index 42433d2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-names-nukie-commander-1 = Commander
-names-nukie-agent-1 = Agent
-names-nukie-operator-1 = Operator
diff --git a/Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl b/Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl
new file mode 100644 (file)
index 0000000..2060315
--- /dev/null
@@ -0,0 +1,23 @@
+random-metadata-name-format-default = {$part0}
+random-metadata-description-format-default = {$part0}
+
+# Used for standard humanoid names - "<firstName> <lastName>"
+name-format-standard = {$part0} {$part1}
+
+name-format-regal-rat = {$part0} {$part1}
+name-format-revenant = The {$part0} of {$part1} {$part2}
+name-format-ninja = {$part0} {$part1}
+name-format-wizard = {$part0} {$part1}
+
+# "<title> <name>"
+name-format-nukie-generic = {$part0} {$part1}
+name-format-nukie-agent = Agent {$part0}
+name-format-nukie-commander = Commander {$part0}
+name-format-nukie-operator = Operator {$part0}
+# "<title> <name>"
+name-format-ert = {$part0} {$part1}
+
+# "<appearance> <type>"
+name-format-book = {$part0} {$part1}
+
+name-format-nuclear-operation = {$part0} {$part1}
diff --git a/Resources/Prototypes/Datasets/Names/joining.yml b/Resources/Prototypes/Datasets/Names/joining.yml
deleted file mode 100644 (file)
index 16ad080..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# These can be inserted inbetween name datasets
-# Ideally it would be localized since just swapping words doesnt help much for a lot of languages
-
-- type: localizedDataset
-  id: WordThe
-  values:
-    prefix: names-word-the-
-    count: 1
-
-- type: localizedDataset
-  id: WordOf
-  values:
-    prefix: names-word-of-
-    count: 1
diff --git a/Resources/Prototypes/Datasets/Names/nukies.yml b/Resources/Prototypes/Datasets/Names/nukies.yml
deleted file mode 100644 (file)
index cf2c6b7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-- type: localizedDataset
-  id: NamesNukieFirstCommander
-  values:
-    prefix: names-nukie-commander-
-    count: 1
-
-- type: localizedDataset
-  id: NamesNukieFirstAgent
-  values:
-    prefix: names-nukie-agent-
-    count: 1
-
-- type: localizedDataset
-  id: NamesNukieFirstOperator
-  values:
-    prefix: names-nukie-operator-
-    count: 1
index 1781ce25cda260424f82e7699a46d8e687a08fa0..89056c1d51916bc7ebfe41c696fd366bf853f846 100644 (file)
     nameSegments:
     - NamesRegalratKingdom
     - NamesRegalratTitle
+    nameFormat: name-format-regal-rat
   - type: GuideHelp
     guides:
     - MinorAntagonists
index dfdb96b35adb3d2517b72954309c333fca01e7bc..1c70e55d66255685910014fc42e5f8f980b5fe5a 100644 (file)
     - StolenEssence
   - type: RandomMetadata
     nameSegments:
-    - WordThe
     - NamesRevenantType
-    - WordOf
     - NamesRevenantAdjective
     - NamesRevenantTheme
+    nameFormat: name-format-revenant
   - type: Speech
     speechVerb: Ghost
   - type: Reactive
index cebc570bdbf83460a75ad27202c73e34775a3a03..5debd3f8a30375761085b7e694f3ae075cc3f458 100644 (file)
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimChiefEngineer
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimCMO
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimHeadOfPersonnel
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimHeadOfSecurity
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimResearchDirector
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: ChallengeVictimQuartermaster
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 # Security
 # Following use EventHumanoidMindShielded since they are heads and probably should have mindshields
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 # Engineering
 
index 11842f30f07099d46c5e4a1e3a2d1ff5d6a9b7ff..8b677c49f705e87576ed88420abc1b39f53f587d 100644 (file)
@@ -68,8 +68,8 @@
   - type: NukeOperative
   - type: RandomMetadata
     nameSegments:
-    - NamesNukieFirstOperator
     - NamesSyndicateNormal
+    nameFormat: name-format-nukie-operator
   - type: Loadout
     prototypes: [SyndicateOperativeGearFullNoUplink]
 
@@ -99,6 +99,7 @@
     nameSegments:
     - NamesSyndicatePrefix
     - NamesSyndicateNormal
+    nameFormat: name-format-nukie-generic
   - type: NpcFactionMember
     factions:
     - Syndicate
index 2d63d48bdc8a4d699b193ded5f9ae8fd5e417b7e..f92cf40e2e4a99eb91ff9c3d8374e2b78376caa3 100644 (file)
@@ -36,6 +36,7 @@
       nameSegments:
         - NamesMilitaryFirstLeader
         - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: DeathSquad
 
@@ -59,6 +60,7 @@
       nameSegments:
         - NamesMilitaryFirstLeader
         - NamesMilitaryLast
+      nameFormat: name-format-ert
 
 
 ## ERT Leader
@@ -75,6 +77,7 @@
       nameSegments:
       - NamesMilitaryFirstLeader
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTLeader
 
       nameSegments:
       - NamesMilitaryFirstLeader
       - NamesMilitaryLast
+      nameFormat: name-format-ert
 
 - type: entity
   id: RandomHumanoidSpawnerERTLeaderEVA
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTChaplain
 
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: Loadout
       prototypes: [ ERTChaplainGear ]
       roleLoadout: [ RoleSurvivalExtended ]
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTJanitor
 
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: Loadout
       prototypes: [ ERTJanitorGear ]
       roleLoadout: [ RoleSurvivalExtended ]
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTEngineer
 
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: Loadout
       prototypes: [ ERTEngineerGear ]
       roleLoadout: [ RoleSurvivalExtended ]
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTSecurity
 
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: Loadout
       prototypes: [ ERTSecurityGear ]
       roleLoadout: [ RoleSurvivalExtended ]
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: RandomHumanoidSpawner
       settings: ERTMedical
 
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
     - type: Loadout
       prototypes: [ ERTMedicalGear ]
       roleLoadout: [ RoleSurvivalExtended ]
       nameSegments:
       - NamesMilitaryFirst
       - NamesMilitaryLast
+      nameFormat: name-format-ert
 
 ## Central Command
 
       nameSegments:
       - NamesFirst
       - NamesLast
+      nameFormat: name-format-standard
 
 - type: randomHumanoidSettings
   id: Cluwne
index 21269366d408c214679e1ca9dc003986b1a1deb9..7b3f4740252f25e08ab49a74a1ce9d914189fc7a 100644 (file)
     nameSegments:
     - BookHintAppearances
     - BookTypes
+    nameFormat: name-format-book
   - type: RandomSprite
     available:
       - cover:
index 8bacfe96af0cb8f38ece250a8f5a0ce7f9698862..a13c2eef9f68654e974dc542fa9bb9202e095e98 100644 (file)
@@ -33,6 +33,7 @@
     nameSegments:
     - NamesSyndicatePrefix
     - NamesSyndicateNormal
+    nameFormat: name-format-nukie-generic
   - type: Damageable
     damageContainer: Inorganic
   - type: ToggleableLightVisuals
index 41655a4871388b1142e47e4153d64054d671c1ab..c369b10949d3ae523d3e925f2ceffe30a4a24be6 100644 (file)
         nameSegments:
         - NamesNinjaTitle
         - NamesNinja
+        nameFormat: name-format-ninja
       mindRoles:
       - MindRoleNinja
 
         nameSegments:
         - NamesWizardFirst
         - NamesWizardLast
+        nameFormat: name-format-wizard
       mindRoles:
       - MindRoleWizard
 
         nameSegments:
         - NamesSyndicatePrefix
         - NamesSyndicateNormal
+        nameFormat: name-format-nukie-generic
       - type: NpcFactionMember
         factions:
         - Syndicate
index a7072bde728d59e303c16921696d5d19fc59c10d..bb855d93aabbc50e5bdcda84cd53fe5009b94e0f 100644 (file)
@@ -97,6 +97,7 @@
     nameSegments:
     - NamesOperationPrefix
     - NamesOperationSuffix
+    nameFormat: name-format-nuclear-operation
   - type: NukeopsRule
   - type: RuleGrids
   - type: AntagSelection
       - type: NukeOperative
       - type: RandomMetadata
         nameSegments:
-        - NamesNukieFirstCommander
         - NamesSyndicateElite
+        nameFormat: name-format-nukie-commander
       - type: NpcFactionMember
         factions:
         - Syndicate
       - type: NukeOperative
       - type: RandomMetadata
         nameSegments:
-        - NamesNukieFirstAgent
         - NamesSyndicateNormal
+        nameFormat: name-format-nukie-agent
       - type: NpcFactionMember
         factions:
         - Syndicate
       - type: NukeOperative
       - type: RandomMetadata
         nameSegments:
-        - NamesNukieFirstOperator
         - NamesSyndicateNormal
+        nameFormat: name-format-nukie-operator
       - type: NpcFactionMember
         factions:
         - Syndicate
         nameSegments:
         - NamesWizardFirst
         - NamesWizardLast
+        nameFormat: name-format-wizard
       mindRoles:
       - MindRoleWizard
 
index 6604a036bdfddd1683846d739ce9214934ab6947..ef80a48cefc63415ca2143afeeaaeb2a3c33dcfa 100644 (file)
@@ -62,5 +62,6 @@
         nameSegments:
         - NamesWizardFirst
         - NamesWizardLast
+        nameFormat: name-format-wizard
       mindRoles:
       - MindRoleWizard