diff --git a/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs
new file mode 100644
index 0000000000..06f4f9edb7
--- /dev/null
+++ b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Chat.Prototypes;
+using Content.Shared.Humanoid;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
+
+namespace Content.Server._Sunrise.ReplacementVocal;
+
+///
+/// Компонент для замены вокальных звуков и эмоций сущности.
+/// Сохраняет предыдущие настройки для возможности восстановления.
+///
+[RegisterComponent]
+public sealed partial class ReplacementVocalComponent : Component
+{
+ [DataField(customTypeSerializer: typeof(PrototypeIdValueDictionarySerializer), required: true)]
+ public Dictionary Vocal;
+
+ [DataField]
+ public HashSet AddedEmotes = new();
+
+ [DataField(customTypeSerializer: typeof(PrototypeIdValueDictionarySerializer))]
+ public Dictionary? PreviousVocal;
+}
diff --git a/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs
new file mode 100644
index 0000000000..b975161c3a
--- /dev/null
+++ b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs
@@ -0,0 +1,72 @@
+using Content.Shared.Humanoid;
+using Content.Shared.Speech;
+using Content.Shared.Speech.Components;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server._Sunrise.ReplacementVocal;
+
+public sealed class ReplacementVocalSystem : EntitySystem
+{
+ [Dependency] private readonly IPrototypeManager _proto = default!;
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnComponentInit);
+ SubscribeLocalEvent(OnComponentShutdown);
+ }
+
+ private void OnComponentInit(EntityUid uid, ReplacementVocalComponent component, ComponentInit args)
+ {
+ if (!TryComp(uid, out var vocalComponent))
+ return;
+
+ if (component.Vocal.Keys == vocalComponent.Sounds?.Keys)
+ return;
+
+ if (!TryComp(uid, out var speechComponent))
+ return;
+
+ component.PreviousVocal = vocalComponent.Sounds;
+
+ vocalComponent.Sounds = component.Vocal;
+
+ LoadEmotes(uid, vocalComponent);
+
+ foreach (var emote in vocalComponent.EmoteSounds!.Sounds.Keys)
+ {
+ if (speechComponent.AllowedEmotes.Contains(emote))
+ continue;
+
+ speechComponent.AllowedEmotes.Add(emote);
+ component.AddedEmotes.Add(emote);
+ }
+ }
+
+ private void OnComponentShutdown(EntityUid uid, ReplacementVocalComponent component, ComponentShutdown args)
+ {
+ if (!TryComp(uid, out var speech))
+ return;
+
+ if (!TryComp(uid, out var vocal))
+ return;
+
+ if (component.PreviousVocal != null)
+ vocal.Sounds = component.PreviousVocal;
+
+ LoadEmotes(uid, vocal);
+
+ foreach (var emote in component.AddedEmotes)
+ {
+ speech.AllowedEmotes.Remove(emote);
+ }
+
+ component.AddedEmotes.Clear();
+ }
+
+ private void LoadEmotes(EntityUid uid, VocalComponent vocalComponent)
+ {
+ var sex = CompOrNull(uid)?.Sex ?? Sex.Unsexed;
+
+ if (vocalComponent.Sounds?.TryGetValue(sex, out var protoId) == true)
+ _proto.TryIndex(protoId, out vocalComponent.EmoteSounds);
+ }
+}
diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl
index 6d3842e941..c66885b3a3 100644
--- a/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl
+++ b/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl
@@ -1,3 +1,5 @@
+trait-category-height = Рост
+trait-category-vocal = Голос
trait-colorblindness-name = Дальтонизм
trait-colorblindness-desc = Вы видите мир не так, как все.
trait-OwOAccent-name = акцент OwO
@@ -16,4 +18,5 @@ trait-tall-quirk-name = высокий
trait-tall-quirk-desc = Делает вас немного выше (Только визуально!).
trait-short-quirk-name = низкий
trait-short-quirk-desc = Делает вас немного ниже (Только визуально!).
-trait-category-height = Рост
+trait-felinid-vocal-name = мурлыкание
+trait-felinid-vocal-desc = Заменяет ваши звуки эмоций фелинидскими. Ня!
diff --git a/Resources/Prototypes/_Sunrise/Traits/categories.yml b/Resources/Prototypes/_Sunrise/Traits/categories.yml
index f80cad0556..ca19cd9576 100644
--- a/Resources/Prototypes/_Sunrise/Traits/categories.yml
+++ b/Resources/Prototypes/_Sunrise/Traits/categories.yml
@@ -2,3 +2,9 @@
id: HeightTraits
name: trait-category-height
maxTraitPoints: 1
+
+- type: traitCategory
+ id: VocalTraits
+ name: trait-category-vocal
+ maxTraitPoints: 1
+
diff --git a/Resources/Prototypes/_Sunrise/Traits/quirks.yml b/Resources/Prototypes/_Sunrise/Traits/quirks.yml
index e4298d23b4..e2193cc350 100644
--- a/Resources/Prototypes/_Sunrise/Traits/quirks.yml
+++ b/Resources/Prototypes/_Sunrise/Traits/quirks.yml
@@ -25,3 +25,16 @@
components:
- type: RescaleSprite
scale: 1,0.9
+
+- type: trait
+ id: FelinidVocal
+ name: trait-felinid-vocal-name
+ description: trait-felinid-vocal-desc
+ category: VocalTraits
+ cost: 1
+ components:
+ - type: ReplacementVocal
+ vocal:
+ Male: MaleFelinid
+ Female: FemaleFelinid
+ Unsexed: MaleFelinid