From 8e27ef22edc030dbbdcbda19ae5bd06c02c94f93 Mon Sep 17 00:00:00 2001 From: comasqw <138010940+comasqw@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:43:02 +0400 Subject: [PATCH] Local helper update (#420) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * local helper update * Delete entities.ftl * Helper Refactor * Revert "Helper Refactor" This reverts commit 4aca315593a08b5f4a03971b3f3a7a19c220a357. * Helper Refactor * Жееесть, я не знал про setdefault у словарей * Update localization_helper.py * Ревёрт "Жееесть, я не знал про setdefault у словарей" Лучше бы я продолжал не знать о них * чтооооо * Update yml_parser.py * Update entities.ftl --------- Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> --- .../ru-RU/_CP14/_PROTO/entities/entities.ftl | 742 ++++++++++++------ Tools/_CP14/LocalizationHelper/base_parser.py | 4 +- .../LocalizationHelper/fluent/ftl_reader.py | 6 +- .../ftl_parser/ftl_parser.py | 4 +- .../LocalizationHelper/localization_helper.py | 136 ++++ Tools/_CP14/LocalizationHelper/main.py | 139 ---- Tools/_CP14/LocalizationHelper/run.bat | 2 +- .../yml_parser/yml_parser.py | 59 +- 8 files changed, 685 insertions(+), 407 deletions(-) create mode 100644 Tools/_CP14/LocalizationHelper/localization_helper.py delete mode 100644 Tools/_CP14/LocalizationHelper/main.py diff --git a/Resources/Locale/ru-RU/_CP14/_PROTO/entities/entities.ftl b/Resources/Locale/ru-RU/_CP14/_PROTO/entities/entities.ftl index 3b2d1e9813..7e78a2c63c 100644 --- a/Resources/Locale/ru-RU/_CP14/_PROTO/entities/entities.ftl +++ b/Resources/Locale/ru-RU/_CP14/_PROTO/entities/entities.ftl @@ -10,19 +10,65 @@ ent-CP14KeyRingInnkeeper = { ent-CP14BaseKeyRing } .desc = { ent-CP14BaseKeyRing.desc } .suffix = Трактирщик +ent-CP14KeyRingAlchemist = { ent-CP14BaseKeyRing } + .desc = { ent-CP14BaseKeyRing.desc } + .suffix = Алхимик + ent-CP14BaseKey = ключ .desc = Небольшой замысловатый кусочек железа, открывающий определенные замки. Не отдавайте кому попало! ent-CP14BaseLockpick = отмычка .desc = Воровской инструмент, позволяющий с достаточными навыками и сноровкой открыть любой замок. -ent-CP14KeyTavern = капитанский ключ +ent-CP14KeyTavernHall = ключ от таверны + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernStaff = ключ от служебных помещений таверны + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernDorms1 = ключ от комнаты таверны 1 + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernDorms2 = ключ от комнаты таверны 2 + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernDorms3 = ключ от комнаты таверны 3 + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernDorms4 = ключ от комнаты таверны 4 + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyTavernDorms5 = ключ от комнаты таверны 5 + .desc = { ent-CP14BaseKey.desc } + +ent-CP14KeyAlchemy = ключ алхимика .desc = { ent-CP14BaseKey.desc } ent-CP14BaseLock = стальной замок .desc = Он запирает вещи. И вам, конечно же, нужен ключ, чтобы открыть их. -ent-CP14LockTavern = капитанский замок +ent-CP14LockTavernHall = замок таверны + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernStaff = замок служебных помещений таверны + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernDorms1 = замок от комнаты таверны 1 + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernDorms2 = замок от комнаты таверны 2 + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernDorms3 = замок от комнаты таверны 3 + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernDorms4 = замок от комнаты таверны 4 + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockTavernDorms5 = замок от комнаты таверны 5 + .desc = { ent-CP14BaseLock.desc } + +ent-CP14LockAlchemy = замок лавки алхимика .desc = { ent-CP14BaseLock.desc } ent-CP14BaseMagicRune = магическая руна @@ -31,6 +77,112 @@ ent-CP14BaseMagicRune = магическая руна ent-CP14BaseMagicImpact = магическая вспышка .desc = проявления магической энергии в физическом плане. +ent-CP14ActionSpellCureWounds = Лечение ран + .desc = Вы касаетесь существа, исцеляя его тело от физических повреждений. + +ent-CP14RuneCureWounds = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectCureWounds = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14ActionSpellEarthWall = Земляная стена + .desc = Поднимает из недр прочную стену земли. + +ent-CP14RuneEarthWall = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectEarthWall = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14ActionSpellFireball = Огненный шар + .desc = Эффективный метод уничтожения - взрывной огненный шар. + +ent-CP14RuneFireball = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectFireball = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14Fireball = исскуственное пламя + +ent-CP14ActionSpellFlameCreation = Создание пламени + .desc = В вашей руке образуется искусственное пламя, освещающее окружающее пространство. Вы можете бросить его, чтобы использовать в качестве одноразового оружия. + +ent-CP14RuneFlameCreation = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectFlameCreation = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14FlameCreationArtificialFlame = искусственное пламя + .desc = Магически созданное искусственное пламя, горящее прямо в воздухе. Неплохой источник света или оружие, если бросить его кому-нибудь в лицо. + +ent-CP14ActionSpellFlashLight = Вспышка света + .desc = Создает вспышку яркого, ослепительного света. + +ent-CP14RuneFlashLight = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectFlashLight = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14ActionSpellIceDagger = Ледяной кинжал + .desc = Материализация временного острого ледяного метательного кинжала. + +ent-CP14RuneIceDagger = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectIceDagger = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14DaggerIce = ледяной кинжал + .desc = Кусок острого магического льда. Через некоторое время действие заклинания ослабнет, и он исчезнет. + +ent-CP14ActionSpellIceFloor = Ледяной пол + .desc = Покрывает определенный участок земли скользким льдом. + +ent-CP14RuneIceFloor = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectIceFloor = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14IceFloor = ледяная корка + .desc = Холодно и скользко. + +ent-CP14ActionSpellIceShards = Ледяные осколки + .desc = Быстрые ледяные иглы для быстрой стрельбы по мишеням. + +ent-CP14RuneIceShards = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14IceShard = ice shard + +ent-CP14ActionSpellShadowGrab = Теневой захват + .desc = Вы вызываете призрачную руку, которая притягивает к вам предмет или сущность. + +ent-CP14ImpactEffectShadowGrab = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14ActionSpellShadowStep = Теневой шаг + .desc = Шаг сквозь прореху реальности, позволяющий быстро преодолеть небольшое расстояние. + +ent-CP14ImpactEffectShadowStep = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14ActionSpellSphereOfLight = Сфера света + .desc = Материализация яркого и безопасного источника света. + +ent-CP14RuneSphereOfLight = { ent-CP14BaseMagicRune } + .desc = { ent-CP14BaseMagicRune.desc } + +ent-CP14ImpactEffectSphereOfLight = { ent-CP14BaseMagicImpact } + .desc = { ent-CP14BaseMagicImpact.desc } + +ent-CP14SphereOfLight = Сфера света + .desc = Сгусток яркого света в форме сферы. + ent-CP14ClothingCloakArmoredRed = бронированная красная накидка .desc = Огромные металлические наплечники дают дополнительную защиту от отрубания головы. @@ -198,6 +350,17 @@ ent-CP14SpawnPointHouseKeeper = завхоз ent-CP14ConstrainedSpawnerBase = Неа .desc = лол +ent-CP14ConstrainedSpawnerXeno = ограниченный спавнер Ксено + .desc = { ent-CP14ConstrainedSpawnerBase.desc } + +ent-CP14RandomSpawnerBattleRoyaleLootWeapon = Лут + .desc = lol + .suffix = Weapon + +ent-CP14RandomSpawnerBattleRoyaleLootTools = Лут + .desc = lol + .suffix = Tools + ent-CP14RandomSpawnerGatherAgaricShroom = спавнер мухоморов ent-CP14RandomDirtLootSpawner = спавнер земли @@ -216,30 +379,27 @@ ent-CP14BiomeSpawnerForest = { ent-CP14BaseBiomeSpawner } .desc = { ent-CP14BaseBiomeSpawner.desc } .suffix = Лес +ent-CP14MobSpaceCobra = кобра + ent-CP14MobDwarf = мистер Дварф - .desc = { ent-CP14BaseMobDwarf.desc } -ent-CP14MobElf = { ent-CP14BaseMobElf } - .desc = { ent-CP14BaseMobElf.desc } +ent-CP14MobElf = мистер Эльф -ent-CP14MobGoblin = { ent-CP14BaseMobGoblin } - .desc = { ent-CP14BaseMobGoblin.desc } +ent-CP14MobGoblin = мистер Гоблин ent-CP14MobHuman = мистер Человек - .desc = { ent-CP14BaseMobHuman.desc } ent-CP14MobTiefling = мистер Тифлинг - .desc = { ent-CP14BaseMobTiefling.desc } -ent-CP14BaseMobDwarf = Мистер Дварф +ent-CP14BaseMobDwarf = мистер Дварф -ent-CP14BaseMobElf = Мистер Эльф +ent-CP14BaseMobElf = мистер Эльф -ent-CP14BaseMobGoblin = Мистер Гоблин +ent-CP14BaseMobGoblin = систер Гоблин -ent-CP14BaseMobHuman = Мистер Человек +ent-CP14BaseMobHuman = мистер Человек -ent-CP14BaseMobTiefling = Мистер Тифлинг +ent-CP14BaseMobTiefling = мистер Тифлинг ent-CP14OreCopper = медная руда .desc = Кусочек бледной, тяжелой меди. @@ -250,33 +410,52 @@ ent-CP14OreIron = железная руда ent-CP14OreGold = золотая руда .desc = Кусочек мягкого, чистого золота. -ent-CP14GreenBottle = Зеленая бутылка +ent-CP14BaseWallpaper = None + .desc = Обои из тонкой бумаги. Их можно наклеить на стены с любых сторон или содрать любым острым предметом. + +ent-CP14WallpaperPink1 = розовые обои + .desc = { ent-CP14BaseWallpaper.desc } + .suffix = 1 + +ent-CP14WallpaperPink30 = { ent-CP14WallpaperPink1 } + .desc = { ent-CP14WallpaperPink1.desc } + .suffix = 30 + +ent-CP14WallpaperGreen1 = зеленые обои + .desc = { ent-CP14BaseWallpaper.desc } + .suffix = 1 + +ent-CP14WallpaperGreen30 = { ent-CP14WallpaperGreen1 } + .desc = { ent-CP14WallpaperGreen1.desc } + .suffix = 30 + +ent-CP14GreenBottle = зеленая бутылка .desc = Зеленая бутылка, идеально подходит для пива. .suffix = Пустая -ent-CP14BlueVial = Синий флакон +ent-CP14BlueVial = синий флакон .desc = Синий флакон, идеально подходит для рома. .suffix = Пустой -ent-CP14GreenVial = Зеленый флакон +ent-CP14GreenVial = зеленый флакон .desc = Маленький зеленый флакон. .suffix = Пустой -ent-CP14OrangeBottle = Оранжевая бутылка +ent-CP14OrangeBottle = оранжевая бутылка .desc = Просто оранжевая бутылка. .suffix = Пустая -ent-CP14RedBottle = Красная бутылка +ent-CP14RedBottle = красная бутылка .desc = Красная бутылка, идеально подходит для вина. .suffix = Пустая -ent-CP14MetalBeerMug = Металлическая кружка +ent-CP14MetalBeerMug = металлическая кружка .desc = Самая обычная металлическая кружка. -ent-CP14WoodenBeerMug = Деревянная кружка +ent-CP14WoodenBeerMug = деревянная кружка .desc = Деревянная кружка для пива. -ent-CP14SteelBeerMug = Пивная кружка +ent-CP14SteelBeerMug = пивная кружка .desc = Деревянная кружка с железными вкраплениями. ent-CP14SteelWoodBeerMug = { ent-CP14SteelBeerMug } @@ -300,6 +479,9 @@ ent-CP14FoodDoughMedium = средний кусок теста ent-CP14FoodDoughMediumFlat = раскатанное тесто .desc = { ent-CP14FoodDoughMedium.desc } +ent-CP14FoodEggBase = None + .desc = Это яйцо! + ent-CP14Eggshells = яичная скорлупа .desc = Ты ходишь по ним, приятель. @@ -318,6 +500,21 @@ ent-CP14FoodMeatLambSlice = кусочки мяса ent-CP14FoodMeatLambCutlet = котлета из баранины .desc = Результат смешивания нарезанной баранины и яйца - сырая круглая котлета. +ent-CP14BasePlate = None + .desc = Это ваша тарелка для вкусного обеда! + +ent-CP14PlateWooden = деревянная тарелка + .desc = { ent-CP14BasePlate.desc } + +ent-CP14PlateWooden2 = { ent-CP14PlateWooden } + .desc = { ent-CP14PlateWooden.desc } + +ent-CP14PlateCeramic = керамическая тарелка + .desc = { ent-CP14BasePlate.desc } + +ent-CP14PlateIron = железная тарелка + .desc = { ent-CP14BasePlate.desc } + ent-CP14FoodCabbage = капуста .desc = Зеленый съедобный шарик @@ -330,53 +527,11 @@ ent-CP14FoodPumpkin = тыква ent-CP14FoodPumpkinSlice = кусок тыквы .desc = Это тыква! -ent-CP14CopperCoin = медная корона - .desc = Минимальная экономическая единица на просторах Эберрона. Является одной десятой серебряного соверена. - .suffix = 10 монет +ent-CP14FoodPotato = картошка + .desc = Такая милаха -ent-CP14CopperCoin5 = { ent-CP14CopperCoin } - .desc = { ent-CP14CopperCoin.desc } - .suffix = 5 монет - -ent-CP14CopperCoin1 = { ent-CP14CopperCoin } - .desc = { ent-CP14CopperCoin.desc } - .suffix = 1 монета - -ent-CP14SilverCoin = серебряный соверен - .desc = Эквивалентен 10 медным коронам, и является одной десятой золотого галифара. - .suffix = 10 монет - -ent-CP14SilverCoin5 = { ent-CP14SilverCoin } - .desc = { ent-CP14SilverCoin.desc } - .suffix = 5 монет - -ent-CP14SilverCoin1 = { ent-CP14SilverCoin } - .desc = { ent-CP14SilverCoin.desc } - .suffix = 1 монета - -ent-CP14GoldCoin = золотой галифар - .desc = Эквивалентен 10 серебряным соверенам, и является одной десятой платинового дракона. - .suffix = 10 монет - -ent-CP14GoldCoin5 = { ent-CP14GoldCoin } - .desc = { ent-CP14GoldCoin.desc } - .suffix = 5 монет - -ent-CP14GoldCoin1 = { ent-CP14GoldCoin } - .desc = { ent-CP14GoldCoin.desc } - .suffix = 1 монета - -ent-CP14PlatinumCoin = платиновый дракон - .desc = Эквивалентен 10 золотым галифарам, и является самой дорогой монетой на просторах Эберрона. - .suffix = 10 монет - -ent-CP14PlatinumCoin5 = { ent-CP14PlatinumCoin } - .desc = { ent-CP14PlatinumCoin.desc } - .suffix = 5 монет - -ent-CP14PlatinumCoin1 = { ent-CP14PlatinumCoin } - .desc = { ent-CP14PlatinumCoin.desc } - .suffix = 1 монета +ent-CP14FoodCucumber = огурец + .desc = Продолговатый зеленый овощ. Освежает! ent-CP14Wallet = кошель .desc = Небольшой кошель, удобный для хранения монет. @@ -385,6 +540,33 @@ ent-CP14WalletFilledTest = { ent-CP14Wallet } .desc = { ent-CP14Wallet.desc } .suffix = Filled test +ent-CP14Wheat = сноп пшеницы + .desc = У вас есть выбор: посадить семена обратно в землю, либо пустить их в муку. + +ent-CP14FlowersRed = красная роза + .desc = Красивые красные розы. Можно использовать для создания красного красителя. + +ent-CP14FlowersYellow = жёлтый днецвет + .desc = Желтый солнечный цветок, пахнущий топленым молоком. Может быть переработан в желтый краситель. + +ent-CP14BloodGrass = кровьтрава + .desc = Самое скучное и распространенное растение, растущее в дикой природе. Известна своими питательными свойствами. + +ent-CP14AgaricMushroom = мухомор + .desc = Этот ядовитый гриб часто можно встретить вблизи водоемов или других влажных мест. Не рекомендуется для употребления в пищу. + +ent-CP14ChromiumSlime = хромиевая слизь + .desc = Это редкое густое вещество можно обнаружить в потоке воды, как будто оно обладает собственным разумом. При попытке изменить саму слизь - она меняет реагент, с которым взаимодействует. + +ent-CP14WildSage = корень дикого шалфея + .desc = Корень повсеместно распространенного лекарственного растения, неплохо заживляющего физические повреждения и вызывающего откашливание. + +ent-CP14QuartzShard = грубый кварц + .desc = природный кристалл, являющийся естественным накопителем магической энергии. Его цвет отражает качество кристалла - чем выше спектр излучения, тем выше уровень утечки энергии. + +ent-CP14LumiMushroom = люмигриб + .desc = Слабо светящийся гриб. Часто используется алхимиками как средство для концентрации растворов. + ent-CP14CopperBar1 = медный слиток .desc = Тяжелый, слегка зеленый кусок обработанной меди. .suffix = 1 @@ -420,6 +602,27 @@ ent-CP14GoldBar10 = { ent-CP14GoldBar1 } .desc = { ent-CP14GoldBar1.desc } .suffix = 10 +ent-CP14BaseDye = краситель + .desc = Яркий, разноцветный краситель, используемый для окрашивания различных предметов. + +ent-CP14DyeRed = красный краситель + .desc = { ent-CP14BaseDye.desc } + +ent-CP14DyeYellow = желтый краситель + .desc = { ent-CP14BaseDye.desc } + +ent-CP14DyeBlue = синий краситель + .desc = { ent-CP14BaseDye.desc } + +ent-CP14DyeGreen = зеленый краситель + .desc = { ent-CP14BaseDye.desc } + +ent-CP14DyePurple = фиолетовый краситель + .desc = { ent-CP14BaseDye.desc } + +ent-CP14DyeBlack = черный краситель + .desc = { ent-CP14BaseDye.desc } + ent-CP14DirtBlock1 = блок земли .desc = Блок великолепной плодородной почвы. @@ -449,13 +652,24 @@ ent-CP14Nail1 = гвозди .desc = Основной столярный инструмент, позволяющий делать с деревом невообразимые вещи. .suffix = 1 -ent-CP14Nail110 = { ent-CP14Nail1 } +ent-CP14Nail10 = { ent-CP14Nail1 } .desc = { ent-CP14Nail1.desc } .suffix = 10 ent-CP14FloraMaterial = растительный материал .desc = Органический материал, используемый в лечебных или строительных целях. +ent-CP14String = нитки + .desc = Тонкая нить. Материал для починки одежды или пошива новой. + +ent-CP14Cloth1 = ткань + .desc = Рулон ткани + .suffix = 1 + +ent-CP14Cloth10 = { ent-CP14Cloth1 } + .desc = { ent-CP14Cloth1.desc } + .suffix = 10 + ent-CP14Cauldron = котел .desc = Тяжелый котелок. Он не такой громоздкий, как чан, но его можно нести в руках. @@ -531,27 +745,6 @@ ent-CP14MeltingMoldThrowableSpear = форма для метательного ent-CP14MeltingMoldTwoHandedSword = форма для двуручного меча .desc = { ent-CP14MeltingMoldBase.desc } -ent-CP14Wheat = сноп пшеницы - .desc = У вас есть выбор: посадить семена обратно в землю, либо пустить их в муку. - -ent-CP14BloodGrass = кровьтрава - .desc = Самое скучное и распространенное растение, растущее в дикой природе. Известна своими питательными свойствами. - -ent-CP14AgaricMushroom = мухомор - .desc = Этот ядовитый гриб часто можно встретить вблизи водоемов или других влажных мест. Не рекомендуется для употребления в пищу. - -ent-CP14ChromiumSlime = хромиевая слизь - .desc = Это редкое густое вещество можно обнаружить в потоке воды, как будто оно обладает собственным разумом. При попытке изменить саму слизь - она меняет реагент, с которым взаимодействует. - -ent-CP14WildSage = корень дикого шалфея - .desc = Корень повсеместно распространенного лекарственного растения, неплохо заживляющего физические повреждения и вызывающего откашливание. - -ent-CP14QuartzShard = грубый кварц - .desc = природный кристалл, являющийся естественным накопителем магической энергии. Его цвет отражает качество кристалла - чем выше спектр излучения, тем выше уровень утечки энергии. - -ent-CP14LumiMushroom = люмигриб - .desc = Слабо светящийся гриб. Часто используется алхимиками как средство для концентрации растворов. - ent-CP14SeedWheat = семена пшеницы .desc = Маленькие семена пшеницы. Что вы будете с ними делать? Размолоть в муку или посадить снова? @@ -561,9 +754,31 @@ ent-CP14SeedPumpkin = семена тыквы ent-CP14SeedCabbage = семена капусты .desc = О нет! Моя капуста! +ent-CP14SeedCucumber = семена огурцов + .desc = Это семена огурцов. Вы знаете, что с ними делать. + ent-CP14SeedTomato = семена помидоров .desc = Похоже на порошок! Они такие маленькие, эти семена. +ent-CP14EnergyCrystalBase = None + .desc = Осколок кристалла, способный накапливать магическую энергию. + +ent-CP14EnergyCrystalSmall = малый энергокристалл + .desc = { ent-CP14EnergyCrystalBase.desc } + .suffix = Full + +ent-CP14EnergyCrystalSmallEmpty = { ent-CP14EnergyCrystalSmall } + .desc = { ent-CP14EnergyCrystalSmall.desc } + .suffix = Empty + +ent-CP14EnergyCrystalMedium = энергокристалл + .desc = { ent-CP14EnergyCrystalBase.desc } + .suffix = Full + +ent-CP14EnergyCrystalMediumEmpty = { ent-CP14EnergyCrystalMedium } + .desc = { ent-CP14EnergyCrystalMedium.desc } + .suffix = Empty + ent-CP14AuraScanner = сканер ауры .desc = Сканирует полярность потоков элементальной энергии в этом месте. @@ -577,6 +792,9 @@ ent-CP14OldLantern = Старая Лампа ent-CP14Rope = веревка .desc = Многофункциональная веревка. Ей можно связать что-нить. Или кого-нибудь. +ent-CP14Scissors = ножницы + .desc = Инструмент для измельчения шерсти, волос, одежды и, при неосторожном обращении, даже пальцев. + ent-CP14BaseSharpeningStone = точильный камень .desc = Позволит заточить притупленное оружие. Если перестараться, вы вполне можете сточить оружие полностью. @@ -631,58 +849,6 @@ ent-CP14BaseLightCrossbow = легкий арбалет ent-CP14Crossbolt = арбалетный болт .desc = Стержень с заостренным концом. Без оперения, это вам не лук. -ent-CP14DungeonEntrance = спуск в подземелье - .desc = Темные глубины подземного мира зовут вас. - -ent-CP14DungeonExit = выход на поверхность - .desc = Выход из темного подземного мира в мир надземный. - -ent-CP14BaseSharpeningStoneStructure = стационарный точильный камень - .desc = Прочный, долговечный точильный камень, способный затачивать оружие без особого вреда для него. - -ent-CP14Mannequin = манекен - .desc = Удобная подставка для одежды или доспехов. - -ent-CP14StatueGob = статуя Гоба - .desc = Он прекрасен. - .suffix = Нормальная - -ent-CP14StatueGobVines = статуя Гоба - .desc = { ent-CP14StatueGob.desc } - .suffix = Нормальная. Заросшая - -ent-CP14StatueGobRuined = разрушенная статуя Гоба - .desc = { ent-CP14StatueGob.desc } - .suffix = Разрушенная - -ent-CP14StatueGobRuinedVines = разрушенная статуя Гоба - .desc = { ent-CP14StatueGob.desc } - .suffix = Разрушенная. Заросшая - -ent-CP14WallmountWoodenBoards = доски - .desc = Прибиты к стене. Зачем? не совсем ясно. - -ent-CP14WallmountWeb = паутина - .desc = Паутина, прилипшая к темным углам, в которой сидят крошечные паучки. - -ent-CP14WallmountVines = лозы - .desc = Робкие ростки сорняков пытаются взобраться по стене вверх, к свету. - -ent-CP14BaseWoodDoor = деревянная дверь - .desc = Не самая прочная конструкция, но это лучше чем ничего. - .suffix = Без замка - -ent-CP14WoodDoorOpened = { ent-CP14BaseWoodDoor } - .desc = { ent-CP14BaseWoodDoor.desc } - .suffix = Открытая - -ent-CP14WoodDoorTavern = { ent-CP14BaseWoodDoor } - .desc = { ent-CP14BaseWoodDoor.desc } - .suffix = Таверна - -ent-CP14FloorWater = вода - .desc = Впадина с обычной водой. Достаточна чиста для употребления. - ent-CP14Chasm = бездна .desc = И вы не видите ее дна... @@ -788,6 +954,124 @@ ent-CP14CrystalDiamondsBig = { ent-CP14CrystalBase } .desc = { ent-CP14CrystalBase.desc } .suffix = White, Big +ent-CP14DungeonEntrance = спуск в подземелье + .desc = Темные глубины подземного мира зовут вас. + +ent-CP14DungeonExit = выход на поверхность + .desc = Выход из темного подземного мира в мир надземный. + +ent-CP14DungeonEntranceAutoLink = { ent-CP14DungeonEntrance } + .desc = { ent-CP14DungeonEntrance.desc } + +ent-CP14DungeonExitAutoLink = { ent-CP14DungeonExit } + .desc = { ent-CP14DungeonExit.desc } + +ent-CP14BaseSharpeningStoneStructure = стационарный точильный камень + .desc = Прочный, долговечный точильный камень, способный затачивать оружие без особого вреда для него. + +ent-CP14Mannequin = манекен + .desc = Удобная подставка для одежды или доспехов. + +ent-CP14StatueGob = статуя Гоба + .desc = Он прекрасен. + .suffix = Нормальная + +ent-CP14StatueGobVines = статуя Гоба + .desc = { ent-CP14StatueGob.desc } + .suffix = Нормальная. Заросшая + +ent-CP14StatueGobRuined = разрушенная статуя Гоба + .desc = { ent-CP14StatueGob.desc } + .suffix = Разрушенная + +ent-CP14StatueGobRuinedVines = разрушенная статуя Гоба + .desc = { ent-CP14StatueGob.desc } + .suffix = Разрушенная. Заросшая + +ent-CP14WallmountWoodenBoards = доски + .desc = Прибиты к стене. Зачем? не совсем ясно. + +ent-CP14WallmountWeb = паутина + .desc = Паутина, прилипшая к темным углам, в которой сидят крошечные паучки. + +ent-CP14WallmountVines = лозы + .desc = Робкие ростки сорняков пытаются взобраться по стене вверх, к свету. + +ent-CP14BaseWoodDoor = деревянная дверь + .desc = Не самая прочная конструкция, но это лучше чем ничего. + .suffix = Without lock + +ent-CP14WoodDoorOpened = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Открытая + +ent-CP14WoodDoorTavernHall = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Hall + +ent-CP14WoodDoorTavernHallOpened = { ent-CP14WoodDoorTavernHall } + .desc = { ent-CP14WoodDoorTavernHall.desc } + .suffix = Tavern Hall, Opened + +ent-CP14WoodDoorTavernStaff = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Staff + +ent-CP14WoodDoorTavernStaffOpened = { ent-CP14WoodDoorTavernStaff } + .desc = { ent-CP14WoodDoorTavernStaff.desc } + .suffix = Tavern Staff, Opened + +ent-CP14WoodDoorTavernDorms1 = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Dorms 1 + +ent-CP14WoodDoorTavernDorms1Opened = { ent-CP14WoodDoorTavernDorms1 } + .desc = { ent-CP14WoodDoorTavernDorms1.desc } + .suffix = Tavern Dorms 1, Opened + +ent-CP14WoodDoorTavernDorms2 = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Dorms 2 + +ent-CP14WoodDoorTavernDorms2Opened = { ent-CP14WoodDoorTavernDorms2 } + .desc = { ent-CP14WoodDoorTavernDorms2.desc } + .suffix = Tavern Dorms 2, Opened + +ent-CP14WoodDoorTavernDorms3 = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Dorms 3 + +ent-CP14WoodDoorTavernDorms3Opened = { ent-CP14WoodDoorTavernDorms3 } + .desc = { ent-CP14WoodDoorTavernDorms3.desc } + .suffix = Tavern Dorms 3, Opened + +ent-CP14WoodDoorTavernDorms4 = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Dorms 4 + +ent-CP14WoodDoorTavernDorms4Opened = { ent-CP14WoodDoorTavernDorms4 } + .desc = { ent-CP14WoodDoorTavernDorms4.desc } + .suffix = Tavern Dorms 4, Opened + +ent-CP14WoodDoorTavernDorms5 = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Tavern Dorms 5 + +ent-CP14WoodDoorTavernDorms5Opened = { ent-CP14WoodDoorTavernDorms5 } + .desc = { ent-CP14WoodDoorTavernDorms5.desc } + .suffix = Tavern Dorms 5, Opened + +ent-CP14WoodDoorTavernAlchemy = { ent-CP14BaseWoodDoor } + .desc = { ent-CP14BaseWoodDoor.desc } + .suffix = Alchemy + +ent-CP14WoodDoorTavernAlchemy5Opened = { ent-CP14WoodDoorTavernAlchemy } + .desc = { ent-CP14WoodDoorTavernAlchemy.desc } + .suffix = Alchemy, Opened + +ent-CP14FloorWater = вода + .desc = Впадина с обычной водой. Достаточна чиста для употребления. + ent-CP14HighBush = высокий куст .desc = Высокие и густые заросли. Возможно кто-то наблюдает за тобой из них. @@ -835,6 +1119,46 @@ ent-CP14FloraTreeLarge05 = { ent-CP14BaseTreeLarge } ent-CP14FloraTreeLarge06 = { ent-CP14BaseTreeLarge } .desc = { ent-CP14BaseTree.desc } +ent-CP14GatherableWildBase = { ent-CP14GatherableBase } + .desc = { ent-CP14GatherableBase.desc } + +ent-CP14GatherablePlantBase = { ent-CP14GatherableBase } + .desc = { ent-CP14GatherableBase.desc } + +ent-CP14GatherableFlowersRed = красные розы + .desc = Красивые красные розы. Можно использовать для создания красного красителя. + .suffix = Gatherable + +ent-CP14GatherableFlowersYellow = желтый днецвет + .desc = Желтый солнечный цветок, пахнущий топленым молоком. Может быть переработан в желтый краситель. + .suffix = Gatherable + +ent-CP14GatherableBloodgrass = кровьтрава + .desc = Самое скучное и распространенное растение, которое можно встретить в природе, - это темно-коричневая трава. + .suffix = Gatherable + +ent-CP14GatherableFlyAgaric = мухоморы + .desc = Этот ядовитый гриб часто можно встретить вблизи водоемов или других влажных мест. Он не рекомендуется для употребления в пищу. + .suffix = Gatherable + +ent-CP14GatherableChromiumSlime = хромиевая слизь + .desc = Это редкое густое вещество можно обнаружить в потоке воды, как будто оно обладает собственным разумом. При попытке изменить саму слизь - она меняет реагент, с которым взаимодействует. + .suffix = Gatherable + +ent-CP14GatherableWildSage = дикий шалфей + .desc = Корень этого повсеместно распространенного лекарственного растения неплохо заживляет физические повреждения и вызывает кашель. + .suffix = Gatherable + +ent-CP14GatherableLumiMushroom = люмигрибы + .desc = Слабо светящийся гриб. Часто используется алхимиками как средство для концентрации растворов. + .suffix = Gatherable + +ent-CP14PlantWheat = пшеница + .desc = Наиболее популярная культура. Непритязательна, и открывает дорогу к разнообразию мучных изделий. + +ent-CP14PlantWheatDeath = мертвая пшеница + .desc = Грустное зрелище потерянной еды. + ent-CP14BaseBarrel = деревянная бочка .desc = Большая, удобная емкость для хранения жидкостей. .suffix = Пустая @@ -888,6 +1212,33 @@ ent-CP14Bonfire = костёр ent-CP14ChairWooden = деревянный стул .desc = Сколочен из самых обычных досок. Просто и эффективно! +ent-CP14BaseCurtains = шторы + .desc = Скрывает то, что не должны видеть другие. + +ent-CP14CurtainsWhite = { ent-CP14BaseCurtains } + .desc = { ent-CP14BaseCurtains.desc } + .suffix = Белые + +ent-CP14CurtainsWhiteOpened = { ent-CP14CurtainsWhite } + .desc = { ent-CP14CurtainsWhite.desc } + .suffix = Белые, открытые + +ent-CP14CurtainsBlue = { ent-CP14BaseCurtains } + .desc = { ent-CP14BaseCurtains.desc } + .suffix = Синие + +ent-CP14CurtainsBlueOpened = { ent-CP14CurtainsBlue } + .desc = { ent-CP14CurtainsBlue.desc } + .suffix = Синие, открытые + +ent-CP14CurtainsRed = { ent-CP14BaseCurtains } + .desc = { ent-CP14BaseCurtains.desc } + .suffix = Красные + +ent-CP14CurtainsRedOpened = { ent-CP14CurtainsRed } + .desc = { ent-CP14CurtainsRed.desc } + .suffix = Красные, открытые + ent-CP14CuttingBoard = Разделочная доска .desc = Поможет вам приготовить еду. @@ -906,20 +1257,17 @@ ent-CP14TableWoodenFrame = каркас деревянного стола ent-CP14TableWooden = деревянный стол .desc = Простой стол, сколоченный из досок. +ent-CP14TableWoodenRound = круглый деревянный стол + .desc = Простой стол из досок. + ent-CP14WallmountTorch = настенный факел .desc = Хороший, надёжный источник света. Жаль, недолговечный. +ent-CP14WallmountTorchAlwaysPowered = вечногорящий настенный факел + ent-CP14WallmountLamp = вечная лампа .desc = Хрупкий вечный голубой огонь как доказательство превосходства магии над природой. -ent-CP14WallmountBarShelfA = bar shelf - .desc = buba. - .suffix = 1 - -ent-CP14WallmountBarShelfB = { ent-CP14WallmountBarShelfA } - .desc = { ent-CP14WallmountBarShelfA.desc } - .suffix = 2 - ent-CP14Workbench = верстак .desc = Стол для создания различного базового инструментария. @@ -929,12 +1277,12 @@ ent-CP14WorkbenchMeltingMolds = стол для резки форм ent-CP14WorkbenchCooking = кухонный стол .desc = Время готовить. +ent-CP14WorkbenchSewing = ткацкий станок + .desc = Время готовить. + ent-CP14FrameWooden = каркас деревянной стены .desc = Деревянный каркас для деревянных стен любых видов. -ent-CP14AlchemyFurnaceDebug = { ent-CP14AlchemyFurnace } - .desc = { ent-CP14AlchemyFurnace.desc } - ent-CP14AlchemyFurnace = алхимическая печь .desc = Печь, работающая на дровах, угле или любом другом горящем материале. Удобна для подогрева алхимических зелий. @@ -947,41 +1295,6 @@ ent-CP14BaseVat = чан ent-CP14SeedbedWooden = грядка .desc = Деревянная кадка с кучей земли, приспособленная для выращивания растений. -ent-CP14GatherableWildBase = { ent-CP14GatherableBase } - .desc = { ent-CP14GatherableBase.desc } - -ent-CP14GatherablePlantBase = { ent-CP14GatherableBase } - .desc = { ent-CP14GatherableBase.desc } - -ent-CP14GatherableBloodgrass = кровьтрава - .desc = Самое скучное и распространенное растение, которое можно встретить в природе, - это темно-коричневая трава. - .suffix = Gatherable - -ent-CP14GatherableFlyAgaric = мухоморы - .desc = Этот ядовитый гриб часто можно встретить вблизи водоемов или других влажных мест. Он не рекомендуется для употребления в пищу. - .suffix = Gatherable - -ent-CP14GatherableChromiumSlime = хромиевая слизь - .desc = Это редкое густое вещество можно обнаружить в потоке воды, как будто оно обладает собственным разумом. При попытке изменить саму слизь - она меняет реагент, с которым взаимодействует. - .suffix = Gatherable - -ent-CP14GatherableWildSage = дикий шалфей - .desc = Корень этого повсеместно распространенного лекарственного растения неплохо заживляет физические повреждения и вызывает кашель. - .suffix = Gatherable - -ent-CP14GatherableLumiMushroom = люмигрибы - .desc = Слабо светящийся гриб. Часто используется алхимиками как средство для концентрации растворов. - .suffix = Gatherable - -ent-CP14PlantWheat = пшеница - .desc = Наиболее популярная культура. Непритязательна, и открывает дорогу к разнообразию мучных изделий. - -ent-CP14PlantWheatDeath = мертвая пшеница - .desc = Грустное зрелище потерянной еды. - -ent-CP14ElementalReactor = elemental reactor - .desc = A work of art created by the dwarves of Zilagro and House Lyrandar, controlling the fire elemental and allowing it to produce vast amounts of energy. - ent-CP14ChestGeneric = сундук .desc = Chest. @@ -1026,6 +1339,11 @@ ent-CP14CliffEndRight = { ent-CP14Cliff } .desc = { ent-CP14Cliff.desc } .suffix = Правый край +ent-CP14DirectionalPlateBase = plate + +ent-CP14DirectionalPlateSteel = armored iron plate + .desc = An iron plate suitable for both blocking passageways and additional wall protection. + ent-CP14IronGrilleBase = железная решетка .desc = Прочный барьер из сваренных вместе железных прутьев. @@ -1089,6 +1407,9 @@ ent-CP14WallCyan = голубая стена ent-CP14WallSkulls = черепная стена .desc = { ent-CP14BaseWall.desc } +ent-CP14WallSteel = стальная стена + .desc = { ent-CP14BaseWall.desc } + ent-CP14BaseFenceWood = деревянный забор .desc = Деревянный кусок ограды. Надеюсь, за ним находится сад бабушки. @@ -1186,48 +1507,3 @@ ent-CP14RawFoodMeat = Сырая баранина ent-CP14CookedFoodMeat = Стейк из баранины .desc = Зажаренный кусок мяса. Запах первобытный. -ent-CP14ActionSpellCureWounds = Лечение ран - .desc = Вы касаетесь существа, исцеляя его тело от физических повреждений. - -ent-CP14ActionSpellEarthWall = Земляная стена - .desc = Поднимает из недр прочную стену земли. - -ent-CP14ActionSpellFireball = Огненный шар - .desc = Эффективный метод уничтожения - взрывной огненный шар. - -ent-CP14ActionSpellFlameCreation = Создание пламени - .desc = В вашей руке образуется искусственное пламя, освещающее окружающее пространство. Вы можете бросить его, чтобы использовать в качестве одноразового оружия. - -ent-CP14FlameCreationArtificialFlame = искусственное пламя - .desc = Магически созданное искусственное пламя, горящее прямо в воздухе. Неплохой источник света или оружие, если бросить его кому-нибудь в лицо. - -ent-CP14ActionSpellFlashLight = Вспышка света - .desc = Создает вспышку яркого, ослепительного света. - -ent-CP14ActionSpellIceDagger = Ледяной кинжал - .desc = Материализация временного острого ледяного метательного кинжала. - -ent-CP14DaggerIce = ледяной кинжал - .desc = Кусок острого магического льда. Через некоторое время действие заклинания ослабнет, и он исчезнет. - -ent-CP14ActionSpellIceFloor = Ледяной пол - .desc = Покрывает определенный участок земли скользким льдом. - -ent-CP14IceFloor = ледяная корка - .desc = Холодно и скользко. - -ent-CP14ActionSpellIceShards = Ледяные осколки - .desc = Быстрые ледяные иглы для быстрой стрельбы по мишеням. - -ent-CP14ActionSpellShadowGrab = Теневой захват - .desc = Вы вызываете призрачную руку, которая притягивает к вам предмет или сущность. - -ent-CP14ActionSpellShadowStep = Теневой шаг - .desc = Шаг сквозь прореху реальности, позволяющий быстро преодолеть небольшое расстояние. - -ent-CP14ActionSpellSphereOfLight = Сфера света - .desc = Материализация яркого и безопасного источника света. - -ent-CP14SphereOfLight = Сфера света - .desc = Сгусток яркого света в форме сферы. - diff --git a/Tools/_CP14/LocalizationHelper/base_parser.py b/Tools/_CP14/LocalizationHelper/base_parser.py index f44b5c4fec..f9b2d7ddb8 100644 --- a/Tools/_CP14/LocalizationHelper/base_parser.py +++ b/Tools/_CP14/LocalizationHelper/base_parser.py @@ -10,7 +10,7 @@ class BaseParser: def __init__(self, paths: tuple): self.path, self.errors_path = paths - def get_files_paths(self) -> list: + def _get_files_paths(self) -> list: """ The method gets the path to the yml folder of localization prototypes/files, e.g. "ftl", then with the help of os library goes through each file in @@ -31,7 +31,7 @@ class BaseParser: json.dump(prototypes, json_file, indent=4) @staticmethod - def check_file_extension(path: str, extension: str) -> bool: + def _check_file_extension(path: str, extension: str) -> bool: if path.endswith(extension): return True return False diff --git a/Tools/_CP14/LocalizationHelper/fluent/ftl_reader.py b/Tools/_CP14/LocalizationHelper/fluent/ftl_reader.py index b6cdd82f09..8935763cc7 100644 --- a/Tools/_CP14/LocalizationHelper/fluent/ftl_reader.py +++ b/Tools/_CP14/LocalizationHelper/fluent/ftl_reader.py @@ -4,9 +4,7 @@ def read_ftl(paths: tuple) -> dict: file and determines by the indentation in the line whether it is a new prototype or an attribute of an old one. """ - prototypes = { - - } + prototypes = {} last_prototype = "" path, error_log_path = paths @@ -36,4 +34,4 @@ def read_ftl(paths: tuple) -> dict: with open(error_log_path, "a") as file: file.write(f"FTL-ERROR:\nAn error occurred while reading a file {path}, error - {e}\n") - return prototypes \ No newline at end of file + return prototypes diff --git a/Tools/_CP14/LocalizationHelper/ftl_parser/ftl_parser.py b/Tools/_CP14/LocalizationHelper/ftl_parser/ftl_parser.py index 1b0a2165e2..1040986e94 100644 --- a/Tools/_CP14/LocalizationHelper/ftl_parser/ftl_parser.py +++ b/Tools/_CP14/LocalizationHelper/ftl_parser/ftl_parser.py @@ -15,9 +15,9 @@ class FTLParser(BaseParser): """ prototypes = {} - for path in self.get_files_paths(): + for path in self._get_files_paths(): - if not self.check_file_extension(path, ".ftl"): + if not self._check_file_extension(path, ".ftl"): continue file = ftl_reader.read_ftl((path, self.errors_path)) diff --git a/Tools/_CP14/LocalizationHelper/localization_helper.py b/Tools/_CP14/LocalizationHelper/localization_helper.py new file mode 100644 index 0000000000..2f633654a6 --- /dev/null +++ b/Tools/_CP14/LocalizationHelper/localization_helper.py @@ -0,0 +1,136 @@ +import json +import os +from yml_parser import YMLParser +from ftl_parser import FTLParser +from fluent import ftl_writer + +# Config constants +CONFIG_PATH = "config.json" +CONFIG_PATHS_KEY_NAME = "paths" +PROTOTYPES_PATH_IN_CONFIG = "prototypes" +FTL_PATH_IN_CONFIG = "localization" +ERRORS_LOG_PATH_IN_CONFIG = "error_log_path" +PARSED_PROTOTYPES_PATH_IN_LAST_LAUNCH = "yml_parser_last_launch" + +LAST_LAUNCH_PROTOTYPES_DIR_NAME = "last_launch" +NAME_OF_FILE_TO_SAVE = "entities.ftl" + + +class LocalizationHelper: + + if not os.path.isdir(LAST_LAUNCH_PROTOTYPES_DIR_NAME): + os.mkdir(LAST_LAUNCH_PROTOTYPES_DIR_NAME) + + def __init__(self, config_path: str): + self._config = self._read_config(config_path) + self._prototypes_path, self._localization_path, self._errors_log_path, self._yml_parser_last_launch = self._get_paths() + self._clear_logs() + self.prototypes_dict_yml = YMLParser((self._prototypes_path, self._errors_log_path)).yml_parser() + self.prototypes_dict_ftl = FTLParser((self._localization_path, self._errors_log_path)).ftl_parser() + self._check_changed_attrs() + self.prototypes = {**self.prototypes_dict_yml, **self.prototypes_dict_ftl} + + def _clear_logs(self): + with open(self._errors_log_path, "w") as file: + file.write("") + + @staticmethod + def _read_config(config_path: str) -> dict: + with open(config_path, "r", encoding="utf-8") as file: + return json.load(file) + + def _get_paths(self) -> tuple: + paths_dict = self._config[CONFIG_PATHS_KEY_NAME] + prototypes_path = paths_dict[PROTOTYPES_PATH_IN_CONFIG] + localization_path = paths_dict[FTL_PATH_IN_CONFIG] + errors_log_path = paths_dict[ERRORS_LOG_PATH_IN_CONFIG] + yml_parser_last_launch = paths_dict[PARSED_PROTOTYPES_PATH_IN_LAST_LAUNCH] + return prototypes_path, localization_path, errors_log_path, yml_parser_last_launch + + def _check_changed_attrs(self): + """ + + What error it fixes - without this function, changed attributes of prototypes that have not been changed in + localization files will simply not be added to the original ftl file, because the script first of all takes data + from localization files, if they exist, of course + + The function gets the data received during the last run of the script, and checks if some attribute from + the last run has been changed,then simply replaces with this attribute the attribute + of the prototype received during parsing of localization files. + """ + if os.path.isfile(self._yml_parser_last_launch): + with open(self._yml_parser_last_launch, 'r', encoding='utf-8') as file: + last_launch_prototypes = json.load(file) + + if last_launch_prototypes: + for prototype, last_launch_attrs in last_launch_prototypes.items(): + if prototype in self.prototypes_dict_yml: + if prototype in self.prototypes_dict_ftl: + attrs = self.prototypes_dict_ftl[prototype] + proto_attrs_in_yml = self.prototypes_dict_yml[prototype] + + for key, value in proto_attrs_in_yml.items(): + if value != last_launch_attrs.get(key): + attrs[key] = value + + self.prototypes_dict_ftl[prototype] = attrs + else: + if prototype in self.prototypes_dict_ftl: + del self.prototypes_dict_ftl[prototype] + + @staticmethod + def _save_result(entities: str) -> None: + with open(NAME_OF_FILE_TO_SAVE, "w", encoding="utf-8") as file: + file.write(entities) + + print(f"{NAME_OF_FILE_TO_SAVE} has been created\n") + + @staticmethod + def _print_errors_log_info(errors_log_path: str, prototypes: dict) -> None: + with open(errors_log_path, "r") as file: + errors = file.read() + + successful_count = len(prototypes) - errors.count("ERROR") + print(f"""Of the {len(prototypes)} prototypes, {successful_count} were successfully processed. + + Errors can be found in {errors_log_path} + Number of errors during YML processing - {errors.count("YML-ERROR")} + Number of errors during FTL processing - {errors.count("FTL-ERROR")} + Number of errors during data extraction and creation of new FTL - {errors.count("RETRIEVING-ERROR")}""") + + def main(self): + entities_ftl = "" + for prototype, prototype_attrs in self.prototypes.items(): + try: + # This fragment is needed to restore some attributes after connecting the dictionary of + # prototypes parsed from ftl with the dictionary of prototypes parsed from yml. + if prototype in self.prototypes_dict_yml: + parent = self.prototypes_dict_yml[prototype]["parent"] + + if parent and not isinstance(parent, list) and parent in self.prototypes_dict_yml: + if not prototype_attrs.get("name"): + prototype_attrs["name"] = f"{{ ent-{parent} }}" + + if not prototype_attrs.get("desc"): + prototype_attrs["desc"] = f"{{ ent-{parent}.desc }}" + + if not prototype_attrs.get("suffix"): + if self.prototypes_dict_yml[prototype].get("suffix"): + prototype_attrs["suffix"] = self.prototypes_dict_yml[prototype]["suffix"] + + if any(prototype_attrs[attr] is not None for attr in ("name", "desc", "suffix")): + proto_ftl = ftl_writer.create_ftl(prototype, self.prototypes[prototype]) + entities_ftl += proto_ftl + except Exception as e: + with open(self._errors_log_path, "a") as file: + print(prototype, prototype_attrs) + file.write( + f"RETRIEVING-ERROR:\nAn error occurred while retrieving data to be written to the file - {e}\n") + + self._save_result(entities_ftl) + self._print_errors_log_info(self._errors_log_path, self.prototypes) + + +if __name__ == '__main__': + helper = LocalizationHelper(CONFIG_PATH) + helper.main() diff --git a/Tools/_CP14/LocalizationHelper/main.py b/Tools/_CP14/LocalizationHelper/main.py deleted file mode 100644 index 49902461d7..0000000000 --- a/Tools/_CP14/LocalizationHelper/main.py +++ /dev/null @@ -1,139 +0,0 @@ -import json -import os -from yml_parser import YMLParser -from ftl_parser import FTLParser -from fluent import ftl_writer - - -def read_config(): - with open("config.json", "r", encoding="utf-8") as file: - return json.load(file) - - -def get_paths(config: dict): - prototypes_path = config["paths"]["prototypes"] - localization_path = config["paths"]["localization"] - errors_log_path = config["paths"]["error_log_path"] - yml_parser_last_launch = config["paths"]["yml_parser_last_launch"] - return prototypes_path, localization_path, errors_log_path, yml_parser_last_launch - - -def print_errors_log_info(errors_log_path: str, all_prototypes: dict) -> None: - with open(errors_log_path, "r") as file: - errors = file.read() - - successful_count = len(all_prototypes) - errors.count("ERROR") - print(f"""Of the {len(all_prototypes)} prototypes, {successful_count} were successfully processed. - -Errors can be found in {errors_log_path} -Number of errors during YML processing - {errors.count("YML-ERROR")} -Number of errors during FTL processing - {errors.count("FTL-ERROR")} -Number of errors during data extraction and creation of new FTL - {errors.count("RETRIEVING-ERROR")}""") - - -def check_changed_attrs(yml_parser_last_launch: str, prototypes_dict: dict, localization_dict: dict): - """ - - What error it fixes - without this function, changed attributes of prototypes that have not been changed in - localization files will simply not be added to the original ftl file, because the script first of all takes data - from localization files, if they exist, of course - - The function gets the data received during the last run of the script, and checks if some attribute from - the last run has been changed,then simply replaces with this attribute the attribute - of the prototype received during parsing of localization files. - """ - if os.path.isfile(yml_parser_last_launch): - with open(yml_parser_last_launch, 'r', encoding='utf-8') as file: - last_launch_prototypes = json.load(file) - - for prototype, proto_attrs_in_prototypes in prototypes_dict.items(): - if prototype in last_launch_prototypes and prototype in localization_dict: - attrs = localization_dict[prototype] - last_launch_prototype_attrs = last_launch_prototypes[prototype] - - for key, value in proto_attrs_in_prototypes.items(): - if value != last_launch_prototype_attrs[key]: - attrs[key] = value - - localization_dict[prototype] = attrs - - -def save_result(entities: str, file_name: str) -> None: - with open(file_name, "w", encoding="utf-8") as file: - file.write(entities) - - print(f"{file_name} has been created\n") - -def main(): - """ - The function gets paths, creates dictionaries with the help of parsers, - performs various checks, and finally creates ftl file. - """ - - config = read_config() - prototypes_path, localization_path, errors_log_path, yml_parser_last_launch = get_paths(config) - - if not os.path.isdir("last_launch"): - os.mkdir("last_launch") - - with open(errors_log_path, "w") as file: - file.write("") - - yml_parser = YMLParser((prototypes_path, errors_log_path)) - prototypes_dict = yml_parser.yml_parser() - - ftl_parser = FTLParser((localization_path, errors_log_path)) - localization_dict = ftl_parser.ftl_parser() - - check_changed_attrs(yml_parser_last_launch, prototypes_dict, localization_dict) - - with open(yml_parser_last_launch, 'w') as json_file: - json.dump(prototypes_dict, json_file, indent=4) - - # This is where the two dictionaries are merged, and prototypes from - # the localization_dict dictionary are preferably selected. - all_prototypes = {**prototypes_dict, **localization_dict} - entities_ftl = "" - - """ - The function traverses each prototype from the dictionary, checks if it has a parent, - and performs certain checks on the attributes of the parent if the prototype does not have its own attributes. - """ - - for prototype in all_prototypes: - prototype_attrs = all_prototypes[prototype] - - try: - if prototype in prototypes_dict: - prototype_attrs["parent"] = prototypes_dict[prototype]["parent"] - parent = prototype_attrs["parent"] - - if not isinstance(parent, list) and parent in prototypes_dict: - if not prototype_attrs.get("name"): - prototype_attrs["name"] = f"{{ ent-{parent} }}" - - if not prototype_attrs.get("desc"): - if parent and not isinstance(parent, list) and prototypes_dict.get(parent): - prototype_attrs["desc"] = f"{{ ent-{parent}.desc }}" - - if not prototype_attrs.get("suffix"): - if prototypes_dict[prototype].get("suffix"): - prototype_attrs["suffix"] = prototypes_dict[prototype]["suffix"] - - if any(prototype_attrs[attr] is not None for attr in ["name", "desc", "suffix"]): - proto_ftl = ftl_writer.create_ftl(prototype, all_prototypes[prototype]) - entities_ftl += proto_ftl - - except Exception as e: - with open(errors_log_path, "a") as file: - print(prototype, prototype_attrs) - file.write(f"RETRIEVING-ERROR:\nAn error occurred while retrieving data to be written to the file - {e}\n") - - file_name = "entities.ftl" - save_result(entities_ftl, file_name) - - print_errors_log_info(errors_log_path, all_prototypes) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/Tools/_CP14/LocalizationHelper/run.bat b/Tools/_CP14/LocalizationHelper/run.bat index c083a40942..e8650b26f5 100644 --- a/Tools/_CP14/LocalizationHelper/run.bat +++ b/Tools/_CP14/LocalizationHelper/run.bat @@ -1,3 +1,3 @@ @echo off -python main.py +python localization_helper.py pause diff --git a/Tools/_CP14/LocalizationHelper/yml_parser/yml_parser.py b/Tools/_CP14/LocalizationHelper/yml_parser/yml_parser.py index 001691b9af..34be5fb07c 100644 --- a/Tools/_CP14/LocalizationHelper/yml_parser/yml_parser.py +++ b/Tools/_CP14/LocalizationHelper/yml_parser/yml_parser.py @@ -1,5 +1,6 @@ import yaml from base_parser import BaseParser +import re class YMLParser(BaseParser): @@ -8,7 +9,7 @@ class YMLParser(BaseParser): """ @staticmethod - def check_proto_attrs(prototype: dict) -> bool: + def _check_proto_attrs(prototype: dict) -> bool: """ The function checks that the prototype at least has some attribute from the "attrs_lst". """ @@ -21,7 +22,7 @@ class YMLParser(BaseParser): return any(prototype.get(attr) is not None for attr in attrs_lst) @staticmethod - def get_proto_attrs(prototypes: dict, prototype: dict) -> None: + def _get_proto_attrs(prototypes: dict, prototype: dict) -> None: prototypes[prototype.get("id")] = { "parent": prototype.get("parent"), "name": prototype.get("name"), @@ -29,18 +30,29 @@ class YMLParser(BaseParser): "suffix": prototype.get("suffix") } - @staticmethod - def create_proto(file) -> str: - proto = "" - for line in file.readlines(): - # The PyYaml library cannot handle the following SpaceStation 14 prototype syntax - !type: ... - # We need to fix this :( - if "!type" in line: - continue - proto += line + def _load_proto(self, file, path) -> list[dict]: + content_str = file.read() + prototypes_lst = re.split(r"\n(?=- type:)", content_str) - return proto + prototypes = [] + for proto in prototypes_lst: + try: + prototype_str = "" + for line in proto.splitlines(): + if "components:" in line: + break + prototype_str += f"{line}\n" + prototype = yaml.safe_load(prototype_str) + if prototype is None: + continue + prototypes.append(prototype[0]) + except Exception as e: + with open(self.errors_path, "a") as error_file: + error_file.write( + f"YML-ERROR:\nAn error occurred during prototype processing {path}, error - {e}\n") + return prototypes + def yml_parser(self) -> dict: """ The function gets the path, then with the help of the os library @@ -49,21 +61,16 @@ class YMLParser(BaseParser): """ prototypes = {} - for path in self.get_files_paths(): - if not self.check_file_extension(path, ".yml"): + for path in self._get_files_paths(): + if not self._check_file_extension(path, ".yml"): continue - try: - with open(path, encoding="utf-8") as file: - proto = self.create_proto(file) - data = yaml.safe_load(proto) - except Exception as e: - with open(self.errors_path, "a") as file: - file.write(f"YML-ERROR:\nAn error occurred during prototype processing {path}, error - {e}\n") - else: - if data is not None: - for prototype in data: - if self.check_proto_attrs(prototype): - self.get_proto_attrs(prototypes, prototype) + with open(path, encoding="utf-8") as file: + content = self._load_proto(file, path) + + if content is not None: + for prototype in content: + if self._check_proto_attrs(prototype): + self._get_proto_attrs(prototypes, prototype) return prototypes