From 9e7ddcc7716dc2f7aa0972ae12fea223f18835ff Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Tue, 26 Apr 2011 20:49:33 +0200 Subject: [PATCH] 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. --- doc/version.txt | 2 +- gen/__init__.py | 6 +- gen/plone25/mixins/__init__.py | 1 + gen/plone25/skin/page.pt | 2 - gen/plone25/wrappers/TranslationWrapper.py | 7 +- shared/data/CountryCodesIso3166.1.txt | 249 +++++++++++++++++++++ shared/data/__init__.py | 45 +++- 7 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 shared/data/CountryCodesIso3166.1.txt diff --git a/doc/version.txt b/doc/version.txt index ef5e445..05e8a45 100644 --- a/doc/version.txt +++ b/doc/version.txt @@ -1 +1 @@ -0.6.5 +0.6.6 diff --git a/gen/__init__.py b/gen/__init__.py index 6442036..4c3956b 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -8,7 +8,7 @@ from appy.gen.utils import sequenceTypes, GroupDescr, Keywords, FileWrapper, \ getClassName, SomeObjects import appy.pod 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 # Default Appy permissions ----------------------------------------------------- @@ -1066,7 +1066,7 @@ class String(Type): # Maximum size is 34 chars if (len(v) < 8) or (len(v) > 34): return False # 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. try: code = int(v[2:4]) @@ -1095,7 +1095,7 @@ class String(Type): for c in value[:4]: if not letter.match(c): return False # 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 # province...). They can only be letters or figures. for c in value[6:]: diff --git a/gen/plone25/mixins/__init__.py b/gen/plone25/mixins/__init__.py index f2a66b5..e2328ab 100644 --- a/gen/plone25/mixins/__init__.py +++ b/gen/plone25/mixins/__init__.py @@ -1245,6 +1245,7 @@ class BaseMixin: res = self.formatText(res, format) # Perform variable replacements for name, repl in mapping.iteritems(): + if not isinstance(repl, basestring): repl = str(repl) res = res.replace('${%s}' % name, repl) return res diff --git a/gen/plone25/skin/page.pt b/gen/plone25/skin/page.pt index e0f6077..42fb431 100644 --- a/gen/plone25/skin/page.pt +++ b/gen/plone25/skin/page.pt @@ -563,8 +563,6 @@ - - diff --git a/gen/plone25/wrappers/TranslationWrapper.py b/gen/plone25/wrappers/TranslationWrapper.py index a95f0e5..3943583 100644 --- a/gen/plone25/wrappers/TranslationWrapper.py +++ b/gen/plone25/wrappers/TranslationWrapper.py @@ -22,9 +22,10 @@ class TranslationWrapper(AbstractWrapper): else: sourceMsg = getattr(sourceTranslation,fieldName) # 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 - # the translation. - if self.request['URL'].endswith('/skyn/edit'): + # This way, the translator sees the HTML tags and can reproduce them + # in the translation. + url = self.request['URL'] + if url.endswith('/skyn/edit') or url.endswith('/skyn/do'): sourceMsg = sourceMsg.replace('<','<').replace('>','>') sourceMsg = sourceMsg.replace('\n', '
') return '
' \ diff --git a/shared/data/CountryCodesIso3166.1.txt b/shared/data/CountryCodesIso3166.1.txt new file mode 100644 index 0000000..86a76ed --- /dev/null +++ b/shared/data/CountryCodesIso3166.1.txt @@ -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 + diff --git a/shared/data/__init__.py b/shared/data/__init__.py index bcfe24f..1e9579a 100644 --- a/shared/data/__init__.py +++ b/shared/data/__init__.py @@ -162,9 +162,10 @@ nativeNames = { } # ------------------------------------------------------------------------------ class Languages: - '''This class gives access to the language codes as standardized by - ISO-639. The file has been downloaded in July 2009 from + '''This class gives access to the language codes and names as standardized + 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)''' + def __init__(self): self.fileName = os.path.dirname(__file__) + '/LanguageCodesIso639.2.txt' self.languageCodes = [] @@ -194,7 +195,7 @@ class Languages: f.close() 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 def get(self, code): @@ -214,7 +215,39 @@ class Languages: res += 'Language: ' + languageCode + ' - ' + self.languageNames[i] res += '\n' 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: @@ -224,18 +257,20 @@ class BelgianCities: https://www.post.be/site/fr/sse/advertising/addressed/biblio.html, converted to CSV (field separator being ";" field content is surrrounded by double quotes).''' + def __init__(self): self.fileName = os.path.dirname(__file__) + '/BelgianCommunes.txt' self.data = {} self.parseFile() + def parseFile(self): f = file(self.fileName) for line in f: if line.strip(): lineElems = line.split(';') self.data[int(lineElems[0].strip('"'))]= lineElems[1].strip('"') + def exists(self, postalCode): '''Is postalCode a valid Belgian postal code?''' return self.data.has_key(postalCode) -# As this is not international, Appy user will instantiate it if needed. # ------------------------------------------------------------------------------