appy.shared: added support for country codes (iso-3166-1) - appy.gen: non-string variables are now allowed in i18n variable replacements; bugfix while browsing translation pages with the 'next' arrows in 'edit' mode.

This commit is contained in:
Gaetan Delannay 2011-04-26 20:49:33 +02:00
parent 4e848ce0a8
commit 9e7ddcc771
7 changed files with 298 additions and 14 deletions

View file

@ -1 +1 @@
0.6.5 0.6.6

View file

@ -8,7 +8,7 @@ from appy.gen.utils import sequenceTypes, GroupDescr, Keywords, FileWrapper, \
getClassName, SomeObjects getClassName, SomeObjects
import appy.pod import appy.pod
from appy.pod.renderer import Renderer from appy.pod.renderer import Renderer
from appy.shared.data import languages from appy.shared.data import countries
from appy.shared.utils import Traceback, getOsTempFolder from appy.shared.utils import Traceback, getOsTempFolder
# Default Appy permissions ----------------------------------------------------- # Default Appy permissions -----------------------------------------------------
@ -1066,7 +1066,7 @@ class String(Type):
# Maximum size is 34 chars # Maximum size is 34 chars
if (len(v) < 8) or (len(v) > 34): return False if (len(v) < 8) or (len(v) > 34): return False
# 2 first chars must be a valid country code # 2 first chars must be a valid country code
if not languages.exists(v[:2].lower()): return False if not countries.exists(v[:2].upper()): return False
# 2 next chars are a control code whose value must be between 0 and 96. # 2 next chars are a control code whose value must be between 0 and 96.
try: try:
code = int(v[2:4]) code = int(v[2:4])
@ -1095,7 +1095,7 @@ class String(Type):
for c in value[:4]: for c in value[:4]:
if not letter.match(c): return False if not letter.match(c): return False
# 2 next chars must be a valid country code # 2 next chars must be a valid country code
if not languages.exists(value[4:6].lower()): return False if not countries.exists(value[4:6].upper()): return False
# Last chars represent some location within a country (a city, a # Last chars represent some location within a country (a city, a
# province...). They can only be letters or figures. # province...). They can only be letters or figures.
for c in value[6:]: for c in value[6:]:

View file

@ -1245,6 +1245,7 @@ class BaseMixin:
res = self.formatText(res, format) res = self.formatText(res, format)
# Perform variable replacements # Perform variable replacements
for name, repl in mapping.iteritems(): for name, repl in mapping.iteritems():
if not isinstance(repl, basestring): repl = str(repl)
res = res.replace('${%s}' % name, repl) res = res.replace('${%s}' % name, repl)
return res return res

View file

@ -563,8 +563,6 @@
<td width="80%"> <td width="80%">
<b class="appyTitle" tal:content="contextObj/title_or_id"></b> <b class="appyTitle" tal:content="contextObj/title_or_id"></b>
</td> </td>
<td><metal:actions use-macro="here/document_actions/macros/document_actions"/>
</td>
</tr> </tr>
<tr tal:define="descrLabel python: contextObj.translate('%s_edit_descr' % contextObj.portal_type)" <tr tal:define="descrLabel python: contextObj.translate('%s_edit_descr' % contextObj.portal_type)"
tal:condition="descrLabel/strip" align="left"> tal:condition="descrLabel/strip" align="left">

View file

@ -22,9 +22,10 @@ class TranslationWrapper(AbstractWrapper):
else: else:
sourceMsg = getattr(sourceTranslation,fieldName) sourceMsg = getattr(sourceTranslation,fieldName)
# When editing the value, we don't want HTML code to be interpreted. # When editing the value, we don't want HTML code to be interpreted.
# This way, the translator sees the HTML tags and can reproduce them in # This way, the translator sees the HTML tags and can reproduce them
# the translation. # in the translation.
if self.request['URL'].endswith('/skyn/edit'): url = self.request['URL']
if url.endswith('/skyn/edit') or url.endswith('/skyn/do'):
sourceMsg = sourceMsg.replace('<','&lt;').replace('>','&gt;') sourceMsg = sourceMsg.replace('<','&lt;').replace('>','&gt;')
sourceMsg = sourceMsg.replace('\n', '<br/>') sourceMsg = sourceMsg.replace('\n', '<br/>')
return '<div class="translationLabel"><acronym title="%s">' \ return '<div class="translationLabel"><acronym title="%s">' \

View file

@ -0,0 +1,249 @@
AFGHANISTAN;AF
ÅLAND ISLANDS;AX
ALBANIA;AL
ALGERIA;DZ
AMERICAN SAMOA;AS
ANDORRA;AD
ANGOLA;AO
ANGUILLA;AI
ANTARCTICA;AQ
ANTIGUA AND BARBUDA;AG
ARGENTINA;AR
ARMENIA;AM
ARUBA;AW
AUSTRALIA;AU
AUSTRIA;AT
AZERBAIJAN;AZ
BAHAMAS;BS
BAHRAIN;BH
BANGLADESH;BD
BARBADOS;BB
BELARUS;BY
BELGIUM;BE
BELIZE;BZ
BENIN;BJ
BERMUDA;BM
BHUTAN;BT
BOLIVIA, PLURINATIONAL STATE OF;BO
BONAIRE, SAINT EUSTATIUS AND SABA;BQ
BOSNIA AND HERZEGOVINA;BA
BOTSWANA;BW
BOUVET ISLAND;BV
BRAZIL;BR
BRITISH INDIAN OCEAN TERRITORY;IO
BRUNEI DARUSSALAM;BN
BULGARIA;BG
BURKINA FASO;BF
BURUNDI;BI
CAMBODIA;KH
CAMEROON;CM
CANADA;CA
CAPE VERDE;CV
CAYMAN ISLANDS;KY
CENTRAL AFRICAN REPUBLIC;CF
CHAD;TD
CHILE;CL
CHINA;CN
CHRISTMAS ISLAND;CX
COCOS (KEELING) ISLANDS;CC
COLOMBIA;CO
COMOROS;KM
CONGO;CG
CONGO, THE DEMOCRATIC REPUBLIC OF THE;CD
COOK ISLANDS;CK
COSTA RICA;CR
CÔTE D'IVOIRE;CI
CROATIA;HR
CUBA;CU
CURAÇAO;CW
CYPRUS;CY
CZECH REPUBLIC;CZ
DENMARK;DK
DJIBOUTI;DJ
DOMINICA;DM
DOMINICAN REPUBLIC;DO
ECUADOR;EC
EGYPT;EG
EL SALVADOR;SV
EQUATORIAL GUINEA;GQ
ERITREA;ER
ESTONIA;EE
ETHIOPIA;ET
FALKLAND ISLANDS (MALVINAS);FK
FAROE ISLANDS;FO
FIJI;FJ
FINLAND;FI
FRANCE;FR
FRENCH GUIANA;GF
FRENCH POLYNESIA;PF
FRENCH SOUTHERN TERRITORIES;TF
GABON;GA
GAMBIA;GM
GEORGIA;GE
GERMANY;DE
GHANA;GH
GIBRALTAR;GI
GREECE;GR
GREENLAND;GL
GRENADA;GD
GUADELOUPE;GP
GUAM;GU
GUATEMALA;GT
GUERNSEY;GG
GUINEA;GN
GUINEA-BISSAU;GW
GUYANA;GY
HAITI;HT
HEARD ISLAND AND MCDONALD ISLANDS;HM
HOLY SEE (VATICAN CITY STATE);VA
HONDURAS;HN
HONG KONG;HK
HUNGARY;HU
ICELAND;IS
INDIA;IN
INDONESIA;ID
IRAN, ISLAMIC REPUBLIC OF;IR
IRAQ;IQ
IRELAND;IE
ISLE OF MAN;IM
ISRAEL;IL
ITALY;IT
JAMAICA;JM
JAPAN;JP
JERSEY;JE
JORDAN;JO
KAZAKHSTAN;KZ
KENYA;KE
KIRIBATI;KI
KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF;KP
KOREA, REPUBLIC OF;KR
KUWAIT;KW
KYRGYZSTAN;KG
LAO PEOPLE'S DEMOCRATIC REPUBLIC;LA
LATVIA;LV
LEBANON;LB
LESOTHO;LS
LIBERIA;LR
LIBYAN ARAB JAMAHIRIYA;LY
LIECHTENSTEIN;LI
LITHUANIA;LT
LUXEMBOURG;LU
MACAO;MO
MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF;MK
MADAGASCAR;MG
MALAWI;MW
MALAYSIA;MY
MALDIVES;MV
MALI;ML
MALTA;MT
MARSHALL ISLANDS;MH
MARTINIQUE;MQ
MAURITANIA;MR
MAURITIUS;MU
MAYOTTE;YT
MEXICO;MX
MICRONESIA, FEDERATED STATES OF;FM
MOLDOVA, REPUBLIC OF;MD
MONACO;MC
MONGOLIA;MN
MONTENEGRO;ME
MONTSERRAT;MS
MOROCCO;MA
MOZAMBIQUE;MZ
MYANMAR;MM
NAMIBIA;NA
NAURU;NR
NEPAL;NP
NETHERLANDS;NL
NEW CALEDONIA;NC
NEW ZEALAND;NZ
NICARAGUA;NI
NIGER;NE
NIGERIA;NG
NIUE;NU
NORFOLK ISLAND;NF
NORTHERN MARIANA ISLANDS;MP
NORWAY;NO
OMAN;OM
PAKISTAN;PK
PALAU;PW
PALESTINIAN TERRITORY, OCCUPIED;PS
PANAMA;PA
PAPUA NEW GUINEA;PG
PARAGUAY;PY
PERU;PE
PHILIPPINES;PH
PITCAIRN;PN
POLAND;PL
PORTUGAL;PT
PUERTO RICO;PR
QATAR;QA
RÉUNION;RE
ROMANIA;RO
RUSSIAN FEDERATION;RU
RWANDA;RW
SAINT BARTHÉLEMY;BL
SAINT HELENA, ASCENSION AND TRISTAN DA CUNHA;SH
SAINT KITTS AND NEVIS;KN
SAINT LUCIA;LC
SAINT MARTIN (FRENCH PART);MF
SAINT PIERRE AND MIQUELON;PM
SAINT VINCENT AND THE GRENADINES;VC
SAMOA;WS
SAN MARINO;SM
SAO TOME AND PRINCIPE;ST
SAUDI ARABIA;SA
SENEGAL;SN
SERBIA;RS
SEYCHELLES;SC
SIERRA LEONE;SL
SINGAPORE;SG
SINT MAARTEN (DUTCH PART);SX
SLOVAKIA;SK
SLOVENIA;SI
SOLOMON ISLANDS;SB
SOMALIA;SO
SOUTH AFRICA;ZA
SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS;GS
SPAIN;ES
SRI LANKA;LK
SUDAN;SD
SURINAME;SR
SVALBARD AND JAN MAYEN;SJ
SWAZILAND;SZ
SWEDEN;SE
SWITZERLAND;CH
SYRIAN ARAB REPUBLIC;SY
TAIWAN, PROVINCE OF CHINA;TW
TAJIKISTAN;TJ
TANZANIA, UNITED REPUBLIC OF;TZ
THAILAND;TH
TIMOR-LESTE;TL
TOGO;TG
TOKELAU;TK
TONGA;TO
TRINIDAD AND TOBAGO;TT
TUNISIA;TN
TURKEY;TR
TURKMENISTAN;TM
TURKS AND CAICOS ISLANDS;TC
TUVALU;TV
UGANDA;UG
UKRAINE;UA
UNITED ARAB EMIRATES;AE
UNITED KINGDOM;GB
UNITED STATES;US
UNITED STATES MINOR OUTLYING ISLANDS;UM
URUGUAY;UY
UZBEKISTAN;UZ
VANUATU;VU
VENEZUELA, BOLIVARIAN REPUBLIC OF;VE
VIET NAM;VN
VIRGIN ISLANDS, BRITISH;VG
VIRGIN ISLANDS, U.S.;VI
WALLIS AND FUTUNA;WF
WESTERN SAHARA;EH
YEMEN;YE
ZAMBIA;ZM
ZIMBABWE;ZW

View file

@ -162,9 +162,10 @@ nativeNames = {
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class Languages: class Languages:
'''This class gives access to the language codes as standardized by '''This class gives access to the language codes and names as standardized
ISO-639. The file has been downloaded in July 2009 from by ISO-639. The file has been downloaded in July 2009 from
http://www.loc.gov/standards/iso639-2/ascii_8bits.html (UTF-8 version)''' http://www.loc.gov/standards/iso639-2/ascii_8bits.html (UTF-8 version)'''
def __init__(self): def __init__(self):
self.fileName = os.path.dirname(__file__) + '/LanguageCodesIso639.2.txt' self.fileName = os.path.dirname(__file__) + '/LanguageCodesIso639.2.txt'
self.languageCodes = [] self.languageCodes = []
@ -194,7 +195,7 @@ class Languages:
f.close() f.close()
def exists(self, code): def exists(self, code):
'''Is p_code a valid 2-digits language/country code?''' '''Is p_code a valid 2-digits language code?'''
return code in self.languageCodes return code in self.languageCodes
def get(self, code): def get(self, code):
@ -214,7 +215,39 @@ class Languages:
res += 'Language: ' + languageCode + ' - ' + self.languageNames[i] res += 'Language: ' + languageCode + ' - ' + self.languageNames[i]
res += '\n' res += '\n'
return res return res
languages = Languages() # As this is international, I instantiate it. # We instantiate here Languages because it is used by the appy.gen languages
# management.
languages = Languages()
# Country codes ISO 3166-1. ----------------------------------------------------
class Countries:
'''This class gives access to the country codes and names as standardized by
ISO 3166-1. The file has been downloaded in March 2011 from
http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm
(first line has been removed).'''
def __init__(self):
self.fileName = os.path.dirname(__file__) + '/CountryCodesIso3166.1.txt'
self.countryCodes = []
# Names of countries in English
self.countryNames = []
self.parseFile()
def parseFile(self):
f = file(self.fileName)
for line in f:
if line.strip():
name, code = line.split(';')
self.countryCodes.append(code.strip())
self.countryNames.append(name.strip())
f.close()
def exists(self, code):
'''Is p_code a valid 2-digits country code?'''
return code in self.countryCodes
# We instantiate here Countries because it is used by appy.gen for some field
# validations.
countries = Countries()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class BelgianCities: class BelgianCities:
@ -224,18 +257,20 @@ class BelgianCities:
https://www.post.be/site/fr/sse/advertising/addressed/biblio.html, https://www.post.be/site/fr/sse/advertising/addressed/biblio.html,
converted to CSV (field separator being ";" field content is surrrounded converted to CSV (field separator being ";" field content is surrrounded
by double quotes).''' by double quotes).'''
def __init__(self): def __init__(self):
self.fileName = os.path.dirname(__file__) + '/BelgianCommunes.txt' self.fileName = os.path.dirname(__file__) + '/BelgianCommunes.txt'
self.data = {} self.data = {}
self.parseFile() self.parseFile()
def parseFile(self): def parseFile(self):
f = file(self.fileName) f = file(self.fileName)
for line in f: for line in f:
if line.strip(): if line.strip():
lineElems = line.split(';') lineElems = line.split(';')
self.data[int(lineElems[0].strip('"'))]= lineElems[1].strip('"') self.data[int(lineElems[0].strip('"'))]= lineElems[1].strip('"')
def exists(self, postalCode): def exists(self, postalCode):
'''Is postalCode a valid Belgian postal code?''' '''Is postalCode a valid Belgian postal code?'''
return self.data.has_key(postalCode) return self.data.has_key(postalCode)
# As this is not international, Appy user will instantiate it if needed.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------