diff --git a/pokedex/data/csv/item_prose.csv b/pokedex/data/csv/item_prose.csv index 325ab54..b20f657 100644 --- a/pokedex/data/csv/item_prose.csv +++ b/pokedex/data/csv/item_prose.csv @@ -247,13 +247,13 @@ Can be smeared on sweet-smelling trees to attract tree-dwelling Pokémon after s : Fully-grown plant will last 25% longer before dying and possibly regrowing." 98,9,,"Used on a path of soil : Plant will regrow after dying 25% more times." -99,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:lileep}. -100,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:anorith}. -101,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:omanyte}. -102,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:kabuto}. -103,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:aerodactyl}. -104,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:shieldon}. -105,9,,Give to a scientist in the {location:mining-museum} in {location:oreburgh-city} or the Museum of Science in {location:pewter-city} to receive a []{pokemon:cranidos}. +99,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:lileep}. +100,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:anorith}. +101,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:omanyte}. +102,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:kabuto}. +103,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:aerodactyl}. +104,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:shieldon}. +105,9,,Give to a scientist in the []{location:mining-museum} in []{location:oreburgh-city} or the Museum of Science in []{location:pewter-city} to receive a []{pokemon:cranidos}. 106,9,Vendor trash.,Vendor trash. 107,9,,"Used on a party Pokémon : Evolves a []{pokemon:minccino} into []{pokemon:cinccino}, a []{pokemon:roselia} into []{pokemon:roserade}, or a []{pokemon:togetic} into []{pokemon:togekiss}." diff --git a/pokedex/data/csv/translations/cs.csv b/pokedex/data/csv/translations/cs.csv index 568533c..9d8cc01 100644 --- a/pokedex/data/csv/translations/cs.csv +++ b/pokedex/data/csv/translations/cs.csv @@ -4,7 +4,7 @@ language_id,table,id,column,source_crc,string 10,Ability,2,name,56942be0,Mrholení 10,Ability,2,short_effect,0d8facc9,"Přivolá [déšť]{mechanic:rain}, který trvá až po ukončení zápasu." 10,Ability,3,name,dbbf77d4,Zrychlení -10,Ability,3,short_effect,56aba85b,Zvýší [Rychlost]{mechanic:speed} o jeden [stupeň]{mechanic:stat modifier} po každém kole. +10,Ability,3,short_effect,56aba85b,Zvýší [Rychlost]{mechanic:speed} o jeden [stupeň]{mechanic:stat-modifier} po každém kole. 10,Ability,4,name,8598e4a6,Bojové brnění 10,Ability,5,name,1456165e,Robustnost 10,Ability,6,name,fc71d5b7,Vlhkost @@ -37,7 +37,7 @@ language_id,table,id,column,source_crc,string 10,Ability,33,name,5ce14a2f,Hbitá plavba 10,Ability,33,short_effect,21665f64,Během [deště]{mechanic:rain} zdvojnásobuje [Rychlost]{mechanic:speed}. 10,Ability,34,name,06f85388,Chlorofyl -10,Ability,34,short_effect,ae2ff9cc,Během [slunečného počasí]{mechanic:strong sunlight} zdvojnásobuje [Rychlost]{mechanic:speed}. +10,Ability,34,short_effect,ae2ff9cc,Během [slunečného počasí]{mechanic:strong-sunlight} zdvojnásobuje [Rychlost]{mechanic:speed}. 10,Ability,35,name,c6497d6e,Osvětlení 10,Ability,36,name,f09afaa5,Kopírování 10,Ability,37,name,7cb6bfd7,Obrovská síla @@ -83,7 +83,7 @@ language_id,table,id,column,source_crc,string 10,AbilityChangelog,1,effect,a881640e,Nemá žádný účinek při zápasu. 10,AbilityChangelog,2,effect,757e1dd8,"Funguje jen proti útokům, které vždy omráčí na jeden úder. (Ne proti těm, které jsou prostě příliš silné.)" 10,AbilityChangelog,3,effect,46cb479e,Nemá žádný účinek v poli. -10,AbilityChangelog,4,effect,8742fa05,"Neabsorbuje nezraňující [elektrické]{type:Electric} útoky, např. [Thunder Wave]{move}." +10,AbilityChangelog,4,effect,8742fa05,"Neabsorbuje nezraňující [elektrické]{type:electric} útoky, např. []{move:thunder-wave}." 10,AbilityChangelog,7,effect,46cb479e,Nemá žádný účinek v poli. 10,AbilityChangelog,8,effect,46cb479e,Nemá žádný účinek v poli. 10,AbilityChangelog,10,effect,46cb479e,Nemá žádný účinek v poli. @@ -840,7 +840,7 @@ language_id,table,id,column,source_crc,string 10,MoveEffect,29,short_effect,4ff5bbff,Okamžitě ukončí zápas s divokým pokémonem. Trenéry donutí vyměnit pokémona. 10,MoveEffect,30,short_effect,e5e4180d,Zaútočí 2-5× za sebou. 10,MoveEffect,32,short_effect,b2aff3a6,"Má $effect_chance% šanci, že se protivník zalekne." -10,MoveEffect,34,effect,cc5f917e,[Těžce otráví]{mechanic:Bad poison} protivníka. +10,MoveEffect,34,effect,cc5f917e,[Těžce otráví]{mechanic:bad-poison} protivníka. 10,MoveEffect,34,short_effect,385d3c02,Vážně otráví protivníka; jed ubere každé kolo více zranění. 10,MoveEffect,35,short_effect,9c649109,Rozsype peníze v hodnotě 5× úrovně uživatele. 10,MoveEffect,36,short_effect,0feee880,Na pět kol sníží zranění ze speciálních útoků o 50%. @@ -859,7 +859,7 @@ language_id,table,id,column,source_crc,string 10,MoveEffect,61,short_effect,ad03d235,Sníží protivníkovi Obranu o dva stupně. 10,MoveEffect,63,short_effect,5ec14f8a,Sníží protivníkovu Speciální obranu o dva stupně. 10,MoveEffect,66,short_effect,a2bdb301,Na pět kol sníží zranění z fyzických útoků o 50%. -10,MoveEffect,67,effect,22a71d53,[Otráví]{mechanic:Poison} protivníka. +10,MoveEffect,67,effect,22a71d53,[Otráví]{mechanic:poison} protivníka. 10,MoveEffect,67,short_effect,7b481e44,Otráví protivníka. 10,MoveEffect,69,short_effect,c981b610,Má $effect_chance% šanci snížit protivníkův Útok o jeden stupeň. 10,MoveEffect,70,short_effect,804b11f9,Má $effect_chance% šanci snížit protivníkovu Obranu o jeden stupeň. @@ -964,27 +964,27 @@ language_id,table,id,column,source_crc,string 10,MoveEffect,338,short_effect,11cd0067,Má $effect_chance% šanci zmást protivníka. 10,MoveEffect,10004,short_effect,c028872e,Sníží protivníkovu Mrštnost o dva stupně. 10,MoveEffect,10006,short_effect,b2988a39,Na pět kol zatemní oblohu. -10,MoveFlag,1,description,66523335,Uživatel se dotkne cíle. Toto zaktivuje některé schopnosti (např. [Static]{ability}) a věci (např. [Sticky Barb]{item}). +10,MoveFlag,1,description,66523335,Uživatel se dotkne cíle. Toto zaktivuje některé schopnosti (např. []{ability:static}) a věci (např. []{item:sticky-barb}). 10,MoveFlag,1,name,e34fed78,Způsobí dotek -10,MoveFlag,2,description,d88ae74f,"Tento útok má nabíjecí kolo, které lze přeskočit pomocí [Power Herbu]{item:Power Herb}." +10,MoveFlag,2,description,d88ae74f,"Tento útok má nabíjecí kolo, které lze přeskočit pomocí []{item:power-herb}." 10,MoveFlag,2,name,877244e9,Má nabíjecí kolo 10,MoveFlag,3,description,6cea8671,"Kolo po použití tohoto útoku přeskočí Pokémon svůj tah, aby se mohl dobít." 10,MoveFlag,3,name,80fd2238,Má dobíjecí kolo -10,MoveFlag,4,description,102038da,"Tento útok nebude fungovat, použil-li cíl toto kolo [Detect]{move} či [Protect]{move}." +10,MoveFlag,4,description,102038da,"Tento útok nebude fungovat, použil-li cíl toto kolo []{move:detect} či [protect]{move:protect}." 10,MoveFlag,4,name,d249c071,Blokované Detectem a Protectem 10,MoveFlag,5,name,b343310a,Odrazitelný -10,MoveFlag,6,description,6d5f5422,"Tento útok bude ukraden, pokud jiný Pokémon toto kolo použil [Snatch]{move}" +10,MoveFlag,6,description,6d5f5422,"Tento útok bude ukraden, pokud jiný Pokémon toto kolo použil []{move:snatch}" 10,MoveFlag,6,name,3a15243a,Ukradnutelný -10,MoveFlag,7,description,25e3b9d0,Pokémon co je cílem tohoto útoku ho může zkopírovat pomocí [Mirror Move]{move} +10,MoveFlag,7,description,25e3b9d0,Pokémon co je cílem tohoto útoku ho může zkopírovat pomocí []{move:mirror-move} 10,MoveFlag,7,name,c4e8a756,Kopírovatelný Mirror Movem 10,MoveFlag,8,name,ae7d93f1,Úderový -10,MoveFlag,9,description,b34264c8,Pokémoni s [Soundproof]{ability} jsou proti tomuto útoku odolní. +10,MoveFlag,9,description,b34264c8,Pokémoni s []{ability:soundproof} jsou proti tomuto útoku odolní. 10,MoveFlag,9,name,752347d8,Zvukový -10,MoveFlag,10,description,ee78fc04,Tento útok nelze použít při [zvýšené gravitaci]{move:Gravity} +10,MoveFlag,10,description,ee78fc04,Tento útok nelze použít při [zvýšené gravitaci]{move:gravity} 10,MoveFlag,10,name,05543fc0,Nepoužitelný s Gravitací 10,MoveFlag,11,description,e68d87da,Tento útok může zmražený pokémon použít k rozmrznutí. 10,MoveFlag,11,name,a2a771b1,Rozmrazí při použití -10,MoveFlag,13,description,5660882a,Tento útok bude blokován [Heal Blockem]{move:Heal Block}. +10,MoveFlag,13,description,5660882a,Tento útok bude blokován pomocí []{move:heal-block}. 10,MoveFlag,13,name,eb08469e,Léčí 10,MoveMetaAilment,1,name,5134bb3b,Paralýza 10,MoveMetaAilment,2,name,cef2eda8,Spánek diff --git a/pokedex/db/multilang.py b/pokedex/db/multilang.py index 0c9a188..54e53ac 100644 --- a/pokedex/db/multilang.py +++ b/pokedex/db/multilang.py @@ -142,6 +142,8 @@ def create_translation_table(_table_name, foreign_class, relation_name, def getset_factory(underlying_type, instance): def getter(translations): text = getattr(translations, column.name) + if text is None: + return text session = object_session(translations) language = translations.local_language return string_getter(text, session, language) diff --git a/pokedex/tests/test_strings.py b/pokedex/tests/test_strings.py index dd02e7d..0b55da3 100644 --- a/pokedex/tests/test_strings.py +++ b/pokedex/tests/test_strings.py @@ -1,6 +1,7 @@ # Encoding: UTF-8 from nose.tools import * +from sqlalchemy.orm.exc import NoResultFound from pokedex.db import tables, connect, util, markdown @@ -102,3 +103,48 @@ class TestStrings(object): print md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident)) assert md.as_html(identifier_url=lambda category, ident: "%s/%s" % (category, ident)) == ( '
') + + def test_markdown_values(self): + """Check all markdown values + + Scans the database schema for Markdown columns, runs through every value + in each, and ensures that it's valid Markdown. + """ + + # Move effects have their own special wrappers. Explicitly test them separately + yield self.check_markdown_column, tables.Move, None, 'effect' + yield self.check_markdown_column, tables.Move, None, 'short_effect' + + for cls in tables.mapped_classes: + for translation_cls in cls.translation_classes: + for column in translation_cls.__table__.c: + if column.info.get('string_getter') == markdown.MarkdownString: + yield self.check_markdown_column, cls, translation_cls, column.name + + def check_markdown_column(self, parent_class, translation_class, column_name): + """Implementation for the above""" + query = self.connection.query(parent_class) + if translation_class: + query = query.join(translation_class) + for item in query: + for language, markdown in getattr(item, column_name + '_map').items(): + + if markdown is None: + continue + + key = u"Markdown in {0} #{1}'s {2} (lang={3})".format( + parent_class.__name__, item.id, column_name, language.identifier) + + try: + text = markdown.as_text() + except NoResultFound: + assert False, u"{0} references something that doesn't exist:\n{1}".format( + key, markdown.source_text) + except AttributeError: + print markdown + raise + + error_message = u"{0} leaves syntax cruft:\n{1}" + error_message = error_message.format(key, text) + + ok_(not any(char in text for char in '[]{}'), error_message)