From tchemit@users.labs.libre-entreprise.org Thu May 14 07:41:03 2009 From: tchemit@users.labs.libre-entreprise.org To: nuiton-utils-commits@list.nuiton.org Subject: [Lutinutil-commits] r1550 - in nuiton-i18n-api/trunk/src/main/java/org/nuiton: . i18n i18n/bundle util Date: Thu, 14 May 2009 07:41:02 +0200 Message-ID: <20090514054102.26C0E461707@labs.libre-entreprise.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7267657007204645654==" --===============7267657007204645654== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Author: tchemit Date: 2009-05-14 05:41:01 +0000 (Thu, 14 May 2009) New Revision: 1550 Added: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/CountryEnum.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nDefaultTooltipFilt= er.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFileReader.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFilter.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nUtil.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/LanguageEnum.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleEntry= .java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleFacto= ry.java nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleScope= .java nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/ nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/LocaleConverter.java Log: migrate to nuiton Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/CountryEnum.java = (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/Countr= yEnum.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/CountryEnum.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/CountryEnum.java 2009= -05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,284 @@ +/*=20 + * *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ +package org.nuiton.i18n; + +/** + * Une =C3=A9num=C3=A9ration pour repr=C3=A9senter le pays d'une locale + *

+ * ISO 3166-1:1998 (= ICS n=C2=B0 01.140.20). + *

+ * la liste des codes + *

+ * Chaque pays est rep=C3=A9sent=C3=A9 ainsi : + *

A2, //     A3     Number Country name
+ * + * @author chemit + */ +public enum CountryEnum { + + AF, // AFG 004 AFGHANISTAN + AL, // ALB 008 ALBANIA + DZ, // DZA 012 ALGERIA + AS, // ASM 016 AMERICAN SAMOA + AD, // AND 020 ANDORRA + AO, // AGO 024 ANGOLA + AI, // AIA 660 ANGUILLA + AQ, // ATA 010 ANTARCTICA + AG, // ATG 028 ANTIGUA AND BARBUDA + AR, // ARG 032 ARGENTINA + AM, // ARM 051 ARMENIA + AW, // ABW 533 ARUBA + AU, // AUS 036 AUSTRALIA + AT, // AUT 040 AUSTRIA + AZ, // AZE 031 AZERBAIJAN + BS, // BHS 044 BAHAMAS + BH, // BHR 048 BAHRAIN + BD, // BGD 050 BANGLADESH + BB, // BRB 052 BARBADOS + BY, // BLR 112 BELARUS + BE, // BEL 056 BELGIUM + BZ, // BLZ 084 BELIZE + BJ, // BEN 204 BENIN + BM, // BMU 060 BERMUDA + BT, // BTN 064 BHUTAN + BO, // BOL 068 BOLIVIA + BA, // BIH 070 BOSNIA AND HERZEGOWINA + BW, // BWA 072 BOTSWANA + BV, // BVT 074 BOUVET ISLAND + BR, // BRA 076 BRAZIL + IO, // IOT 086 BRITISH INDIAN OCEAN TERRITORY + BN, // BRN 096 BRUNEI DARUSSALAM + BG, // BGR 100 BULGARIA + BF, // BFA 854 BURKINA FASO + BI, // BDI 108 BURUNDI + KH, // KHM 116 CAMBODIA + CM, // CMR 120 CAMEROON + CA, // CAN 124 CANADA + CV, // CPV 132 CAPE VERDE + KY, // CYM 136 CAYMAN ISLANDS + CF, // CAF 140 CENTRAL AFRICAN REPUBLIC + TD, // TCD 148 CHAD + CL, // CHL 152 CHILE + CN, // CHN 156 CHINA + CX, // CXR 162 CHRISTMAS ISLAND + CC, // CCK 166 COCOS (KEELING) ISLANDS + CO, // COL 170 COLOMBIA + KM, // COM 174 COMOROS + CG, // COG 178 CONGO + CK, // COK 184 COOK ISLANDS + CR, // CRI 188 COSTA RICA + CI, // CIV 384 COTE D'IVOIRE + HR, // HRV 191 CROATIA (local name: Hrvatska) + CU, // CUB 192 CUBA + CY, // CYP 196 CYPRUS + CZ, // CZE 203 CZECH REPUBLIC + DK, // DNK 208 DENMARK + DJ, // DJI 262 DJIBOUTI + DM, // DMA 212 DOMINICA + DO, // DOM 214 DOMINICAN REPUBLIC + TP, // TMP 626 EAST TIMOR + EC, // ECU 218 ECUADOR + EG, // EGY 818 EGYPT + SV, // SLV 222 EL SALVADOR + GQ, // GNQ 226 EQUATORIAL GUINEA + ER, // ERI 232 ERITREA + EE, // EST 233 ESTONIA + ET, // ETH 210 ETHIOPIA + FK, // FLK 238 FALKLAND ISLANDS (MALVINAS) + FO, // FRO 234 FAROE ISLANDS + FJ, // FJI 242 FIJI + FI, // FIN 246 FINLAND + FR, // FRA 250 FRANCE + FX, // FXX 249 FRANCE, METROPOLITAN + GF, // GUF 254 FRENCH GUIANA + PF, // PYF 258 FRENCH POLYNESIA + TF, // ATF 260 FRENCH SOUTHERN TERRITORIES + GA, // GAB 266 GABON + GM, // GMB 270 GAMBIA + GE, // GEO 268 GEORGIA + DE, // DEU 276 GERMANY + GH, // GHA 288 GHANA + GI, // GIB 292 GIBRALTAR + GR, // GRC 300 GREECE + GL, // GRL 304 GREENLAND + GD, // GRD 308 GRENADA + GP, // GLP 312 GUADELOUPE + GU, // GUM 316 GUAM + GT, // GTM 320 GUATEMALA + GN, // GIN 324 GUINEA + GW, // GNB 624 GUINEA-BISSAU + GY, // GUY 328 GUYANA + HT, // HTI 332 HAITI + HM, // HMD 334 HEARD AND MC DONALD ISLANDS + HN, // HND 340 HONDURAS + HK, // HKG 344 HONG KONG + HU, // HUN 348 HUNGARY + IS, // ISL 352 ICELAND + IN, // IND 356 INDIA + ID, // IDN 360 INDONESIA + IR, // IRN 364 IRAN (ISLAMIC REPUBLIC OF) + IQ, // IRQ 368 IRAQ + IE, // IRL 372 IRELAND + IL, // ISR 376 ISRAEL + IT, // ITA 380 ITALY + JM, // JAM 388 JAMAICA + JP, // JPN 392 JAPAN + JO, // JOR 400 JORDAN + KZ, // KAZ 398 KAZAKHSTAN + KE, // KEN 404 KENYA + KI, // KIR 296 KIRIBATI + KP, // PRK 408 KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF + KR, // KOR 410 KOREA, REPUBLIC OF + KW, // KWT 414 KUWAIT + KG, // KGZ 417 KYRGYZSTAN + LA, // LAO 418 LAO PEOPLE'S DEMOCRATIC REPUBLIC + LV, // LVA 428 LATVIA + LB, // LBN 422 LEBANON + LS, // LSO 426 LESOTHO + LR, // LBR 430 LIBERIA + LY, // LBY 434 LIBYAN ARAB JAMAHIRIYA + LI, // LIE 438 LIECHTENSTEIN + LT, // LTU 440 LITHUANIA + LU, // LUX 442 LUXEMBOURG + MO, // MAC 446 MACAU + MK, // MKD 807 (provis) MACEDONIA, THE FORMER YUGOSLAV REPUBLIC= OF + MG, // MDG 450 MADAGASCAR + MW, // MWI 454 MALAWI + MY, // MYS 458 MALAYSIA + MV, // MDV 462 MALDIVES + ML, // MLI 466 MALI + MT, // MLT 470 MALTA + MH, // MHL 584 MARSHALL ISLANDS + MQ, // MTQ 474 MARTINIQUE + MR, // MRT 478 MAURITANIA + MU, // MUS 480 MAURITIUS + YT, // MYT 175 MAYOTTE + MX, // MEX 484 MEXICO + FM, // FSM 583 MICRONESIA, FEDERATED STATES OF + MD, // MDA 498 MOLDOVA, REPUBLIC OF + MC, // MCO 492 MONACO + MN, // MNG 496 MONGOLIA + MS, // MSR 500 MONTSERRAT + MA, // MAR 504 MOROCCO + MZ, // MOZ 508 MOZAMBIQUE + MM, // MMR 104 MYANMAR + NA, // NAM 516 NAMIBIA + NR, // NRU 520 NAURU + NP, // NPL 524 NEPAL + NL, // NLD 528 NETHERLANDS + AN, // ANT 530 NETHERLANDS ANTILLES + NC, // NCL 540 NEW CALEDONIA + NZ, // NZL 554 NEW ZEALAND + NI, // NIC 558 NICARAGUA + NE, // NER 562 NIGER + NG, // NGA 566 NIGERIA + NU, // NIU 570 NIUE + NF, // NFK 574 NORFOLK ISLAND + MP, // MNP 580 NORTHERN MARIANA ISLANDS + NO, // NOR 578 NORWAY + OM, // OMN 512 OMAN + PK, // PAK 586 PAKISTAN + PW, // PLW 585 PALAU + PA, // PAN 591 PANAMA + PG, // PNG 598 PAPUA NEW GUINEA + PY, // PRY 600 PARAGUAY + PE, // PER 604 PERU + PH, // PHL 608 PHILIPPINES + PN, // PCN 612 PITCAIRN + PL, // POL 616 POLAND + PT, // PRT 620 PORTUGAL + PR, // PRI 630 PUERTO RICO + QA, // QAT 634 QATAR + RE, // REU 638 REUNION + RO, // ROM 642 ROMANIA + RU, // RUS 643 RUSSIAN FEDERATION + RW, // RWA 646 RWANDA + KN, // KNA 659 SAINT KITTS AND NEVIS + LC, // LCA 662 SAINT LUCIA + VC, // VCT 670 SAINT VINCENT AND THE GRENADINES + WS, // WSM 882 SAMOA + SM, // SMR 674 SAN MARINO + ST, // STP 678 SAO TOME AND PRINCIPE + SA, // SAU 682 SAUDI ARABIA + SN, // SEN 686 SENEGAL + SC, // SYC 690 SEYCHELLES + SL, // SLE 694 SIERRA LEONE + SG, // SGP 702 SINGAPORE + SK, // SVK 703 SLOVAKIA (Slovak Republic) + SI, // SVN 705 SLOVENIA + SB, // SLB 090 SOLOMON ISLANDS + SO, // SOM 706 SOMALIA + ZA, // ZAF 710 SOUTH AFRICA + ES, // ESP 724 SPAIN + LK, // LKA 144 SRI LANKA + SH, // SHN 654 ST. HELENA + PM, // SPM 666 ST. PIERRE AND MIQUELON + SD, // SDN 736 SUDAN + SR, // SUR 740 SURINAME + SJ, // SJM 744 SVALBARD AND JAN MAYEN ISLANDS + SZ, // SWZ 748 SWAZILAND + SE, // SWE 752 SWEDEN + CH, // CHE 756 SWITZERLAND + SY, // SYR 760 SYRIAN ARAB REPUBLIC + TW, // TWN 158 TAIWAN, PROVINCE OF CHINA + TJ, // TJK 762 TAJIKISTAN + TZ, // TZA 834 TANZANIA, UNITED REPUBLIC OF + TH, // THA 764 THAILAND + TG, // TGO 768 TOGO + TK, // TKL 772 TOKELAU + TO, // TON 776 TONGA + TT, // TTO 780 TRINIDAD AND TOBAGO + TN, // TUN 788 TUNISIA + TR, // TUR 792 TURKEY + TM, // TKM 795 TURKMENISTAN + TC, // TCA 796 TURKS AND CAICOS ISLANDS + TV, // TUV 798 TUVALU + UG, // UGA 800 UGANDA + UA, // UKR 804 UKRAINE + AE, // ARE 784 UNITED ARAB EMIRATES + GB, // GBR 826 UNITED KINGDOM + US, // USA 840 UNITED STATES + UM, // UMI 581 UNITED STATES MINOR OUTLYING ISLANDS + UY, // URY 858 URUGUAY + UZ, // UZB 860 UZBEKISTAN + VU, // VUT 548 VANUATU + VA, // VAT 336 VATICAN CITY STATE (HOLY SEE) + VE, // VEN 862 VENEZUELA + VN, // VNM 704 VIET NAM + VG, // VGB 092 VIRGIN ISLANDS (BRITISH) + VI, // VIR 850 VIRGIN ISLANDS (U.S.) + WF, // WLF 876 WALLIS AND FUTUNA ISLANDS + EH, // ESH 732 WESTERN SAHARA + YE, // YEM 887 YEMEN + YU, // YUG 891 YUGOSLAVIA + ZR, // ZAR 180 ZAIRE + ZM, // ZMB 894 ZAMBIA + ZW; // ZWE 716 ZIMBABWE + + public static CountryEnum valueOf(String country, CountryEnum defaultVal= ue) { + CountryEnum countryValue =3D null; + try { + countryValue =3D CountryEnum.valueOf(country.toUpperCase()); + } catch (IllegalArgumentException e) { + System.err.println("unfound country " + country + ", will use de= fault one : " + defaultValue); + } catch (NullPointerException e) { + System.err.println("unfound country " + country + ", will use de= fault one : " + defaultValue); + } + return countryValue =3D=3D null ? defaultValue : countryValue; + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/Coun= tryEnum.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nDefaultToolti= pFilter.java (from rev 1543, nuiton-i18n-api/trunk/src/main/java/org/codeluti= n/i18n/I18nDefaultTooltipFilter.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nDefaultTooltipFil= ter.java (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nDefaultTooltipFil= ter.java 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,43 @@ +/* *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ + +/* * + * i18nDefaultTooltipFilter.java + * + * Created: 2 d=C3=A9c. 2003 + * + * @author Benjamin Poussin + * Copyright Code Lutin + * @version $Revision$ + * + * Mise a jour: $Date$ + * par : $Author$ + */ + +package org.nuiton.i18n; + +public class I18nDefaultTooltipFilter implements I18nFilter { // I18nDefault= TooltipFilter + + @Override + public String applyFilter(String message) { + if (message !=3D null && message.startsWith("defaultToolTip-")) { + return null; + } + return message; + } +} // I18nDefaultTooltipFilter + Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFileReader.ja= va (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/I18= nFileReader.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFileReader.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFileReader.java 2= 009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,131 @@ +/* *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ + +/* * + * I18nFileReader.java + * + * Created: Nov 22, 2004 + * + * @author C=C3=A9dric Pineau + * @version $Revision$ + * + * Last update : $Date$ + * by : $Author$ + */ + +package org.nuiton.i18n; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.Properties; +import java.util.regex.Pattern; + +/** Classe assurant la lecture et les possibles traitement n=C3=A9cessaires = =C3=A0 I18n. */ +public class I18nFileReader extends Properties { + + protected static final Pattern commentPattern =3D Pattern.compile("[^\\\= \]#"); + + protected static final Pattern splitPattern =3D Pattern.compile("[^\\\\]= =3D"); + private static final long serialVersionUID =3D 3611718334066783394L; + + public void load(InputStream inStream, String encodingTo) throws IOExcep= tion { + Charset charsetTo =3D Charset.forName(encodingTo); + BufferedReader readerFile; + readerFile =3D new BufferedReader(new InputStreamReader(inStream, ch= arsetTo)); + String lineFile; + StringBuilder builderFile; + builderFile =3D new StringBuilder(); + while ((lineFile =3D readerFile.readLine()) !=3D null) { + builderFile.append(lineFile).append('\n'); + } + readerFile.close(); + super.load(new ByteArrayInputStream(builderFile.toString().getBytes(= ))); + } + + protected String interpretBackslashes(String message) { + int backslashIndex =3D -1; + while ((backslashIndex =3D message.indexOf("\\", backslashIndex + 1)= ) !=3D -1) { + if (message.length() >=3D backslashIndex + 1) { + char charNextToBackslash =3D message.charAt(backslashIndex += 1); + char replacementChar; + switch (charNextToBackslash) { + case '\\': + replacementChar =3D '\\'; + break; + case 't': + replacementChar =3D '\t'; + break; + case 'n': + replacementChar =3D '\n'; + break; + case ' ': + replacementChar =3D ' '; + break; + case '=3D': + replacementChar =3D '=3D'; + break; + case ':': + replacementChar =3D ':'; + break; + default: + replacementChar =3D '\\'; + break; + } + message =3D message.substring(0, backslashIndex) + replaceme= ntChar + message.substring(backslashIndex + 2); + } + } + return message; + } + + private static char[] chars =3D {'\\', '\n', '\t', ' ', '=3D', ':'}; + + protected String serializeBackslashes(String message) { + for (char c : chars) { + int charIndex =3D -1; + while ((charIndex =3D message.indexOf(c, charIndex + 2)) !=3D -1= ) { + String replacementString =3D "" + c; + switch (c) { + case '\\': + replacementString =3D "\\\\"; + break; + case '\t': + replacementString =3D "\\t"; + break; + case '\n': + replacementString =3D "\\n"; + break; + case ' ': + replacementString =3D "\\ "; + break; + case '=3D': + replacementString =3D "\\=3D"; + break; + case ':': + replacementString =3D "\\:"; + break; + } + message =3D message.substring(0, charIndex) + replacementStr= ing + message.substring(charIndex + 1); + } + } + return message; + } + +} //I18nFileReader Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18n= FileReader.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFilter.java (= from rev 1543, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/I18nFil= ter.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFilter.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nFilter.java 2009-= 05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,37 @@ +/* *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ + +/* * + * i18nFilter.java + * + * Created: 2 d=C3=A9c. 2003 + * + * @author Benjamin Poussin + * Copyright Code Lutin + * @version $Revision$ + * + * Mise a jour: $Date$ + * par : $Author$ + */ + +package org.nuiton.i18n; + +public interface I18nFilter { // I18nFilter + + public String applyFilter(String message); +} // I18nFilter + Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nUtil.java (fr= om rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/I18nUtil.= java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nUtil.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18nUtil.java 2009-05= -14 05:41:01 UTC (rev 1550) @@ -0,0 +1,194 @@ +package org.nuiton.i18n; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.logging.Logger; +import java.util.zip.ZipFile; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.LocaleConverter; + +/** + * + * @author chemit + */ +public class I18nUtil { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log =3D LogFactory.getLog(I18nUtil.class); + public static final String ISO_8859_1_ENCONDING =3D "ISO-8859-1"; + public static final String UTF_8_ENCONDING =3D "UTF-8"; + public static final String DEFAULT_ENCODING =3D ISO_8859_1_ENCONDING; + public static final Locale DEFAULT_LOCALE =3D Locale.UK; + + /** + * Parse a list of {@link Locale} seperated by comma. + * + * Example : fr_FR,en_GB + * + * @param str the string representation of locale separated by comma + * @return list of available locales + * @throws IllegalArgumentException ia a locale is not valid + */ + public static Locale[] parseLocales(String str) throws IllegalArgumentEx= ception { + List result =3D new java.util.ArrayList(); + String[] bundlesToUse =3D str.split(","); + for (int i =3D 0, j =3D bundlesToUse.length; i < j; i++) { + String s =3D bundlesToUse[i].trim(); + // on devrait verifier que le bundle existe + try { + Locale l =3D (Locale) new LocaleConverter().convert(Locale.c= lass, s); + result.add(l); + } catch (Exception e) { + throw new IllegalArgumentException("bundle " + s + " is not = a valid locale,e"); + } + } + return result.toArray(new Locale[result.size()]); + } + + public static Locale newLocale(String str) { + if (str =3D=3D null) { + // get use locale + return newLocale(null, null); + } + try { + return (Locale) new LocaleConverter().convert(Locale.class, str); + } catch (Exception e) { + Logger.getLogger("org.codelutin.i18n.I18n").warning("could not l= oad locale '" + str + " for reason : " + e.getMessage()); + // use default locale + return DEFAULT_LOCALE; + } + } + + public static Locale newLocale(String language, String country) { + if (language =3D=3D null) { + // get user locale + language =3D System.getProperty("user.language", DEFAULT_LOCALE.= getLanguage()); + country =3D System.getProperty("user.country", DEFAULT_LOCALE.ge= tCountry()); + } + return newLocale(language + (country =3D=3D null ? "" : '_' + countr= y)); + } + + /** + * Test if an url contains the given directory with no recurse seeking. + * + * @param url the url to seek + * @param directory the directory to find + * @return true if directory was found, false = otherwise. + * @throws java.io.IOException if any io pb + */ + public static boolean containsDirectDirectory(URL url, String directory)= throws IOException { + String fileName =3D url.getFile(); + // TODO deal with encoding in windows, this is very durty, but it wo= rks... + File file =3D new File(fileName.replaceAll("%20", " ")); + if (!file.exists()) { + return false; + } + if (isJar(fileName) || isZip(fileName)) { + // cas ou le fichier du classLoader est un fichier jar ou zip + if (log.isTraceEnabled()) { + log.trace("zip to search " + file); + } + return new ZipFile(file).getEntry(directory + "/") !=3D null; + } + if (file.isDirectory()) { + // cas ou le ichier du classLoader est un repertoire + if (log.isTraceEnabled()) { + log.trace("directory to search " + file); + } + return new File(file, directory).exists(); + } + + if (log.isWarnEnabled()) { + log.warn("unknown resource type " + url); + } + return false; + } + + /** + * Verifie si le fichier est un fichier jar. + * + * @param name nom du fichier a tester + * @return vrai si le fichier se termine par .jar faux sinon + */ + static public boolean isJar(String name) { + if (name !=3D null && name.length() > 4) { + String ext =3D name.substring(name.length() - 4, name.length()); + return ".jar".equalsIgnoreCase(ext); + } + return false; + } + + /** + * Verifie si le fichier est un fichier zip + * + * @param name nom du fichier a tester + * @return vrai si le fichier se termine par .zip faux sinon + */ + static public boolean isZip(String name) { + if (name !=3D null && name.length() > 4) { + String ext =3D name.substring(name.length() - 4, name.length()); + return ".zip".equalsIgnoreCase(ext); + } + return false; + } + + /** + * Retourne la liste des fichiers correspondant au pattern donne, aucun + * ordre ne doit =C3=AAtre suppos=C3=A9 sur les fichiers. + * + * @param repository repertoire dans lequel on recherche les fichiers + * @param pattern le nom du fichier a extraire du fichier du repertoi= re doit + * correspondre au pattern (repertoire + nom compris).= si le + * pattern est null, tous les fichiers trouv=C3=A9 son= t retourn=C3=A9. + * @return la liste des urls correspondant au pattern + */ + static public List getURLsFromDirectory(File repository, String pat= tern) { + try { + if (log.isTraceEnabled()) { + log.trace("search '" + pattern + "' in " + repository); + } + + List urlList =3D new ArrayList(); + File[] filesList =3D repository.listFiles(); + + if (filesList !=3D null) { + + for (File file : filesList) { + + String name =3D file.getAbsolutePath(); + + if (log.isTraceEnabled()) { + log.trace("directory: " + repository + " name: " + n= ame); + } + + // cas de recursivite : repertoire dans un repertoire + if (file.exists() && file.isDirectory()) { + urlList.addAll(getURLsFromDirectory(file, + pattern)); + // si le fichier du repertoire n'est pas un repertoi= re + // on verifie s'il correspond au pattern + } else if (pattern =3D=3D null || name.matches(pattern))= { + URL url =3D file.toURI().toURL(); + if (log.isTraceEnabled()) { + log.trace("directory: " + repository + " url: " = + url); + } + urlList.add(url); + } + } + } + if (log.isTraceEnabled()) { + log.trace("found with pattern '" + pattern + "' : " + urlLis= t); + } + return urlList; + } catch (MalformedURLException eee) { + throw new IllegalArgumentException("Erreur lors de la conversion= de l'url " + repository + " (pattern " + pattern + ") " + eee.getMessage(), = eee); + //throw new ResourceException("Le fichier n'a pu =C3=AAtre conve= rti en URL", eee); + } + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/I18n= Util.java ___________________________________________________________________ Name: svn:mergeinfo +=20 Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/LanguageEnum.java= (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/Langu= ageEnum.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/LanguageEnum.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/LanguageEnum.java 200= 9-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,181 @@ +/*=20 + * *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ +package org.nuiton.i18n; + +/** + * Une =C3=A9num=C3=A9ration pour repr=C3=A9senter le langue d'une locale d= =C3=A9finie dans la norme + * ISO 639-1= :1998 (ICS n=C2=B0 01.140.20). + *

+ * la = liste des codes + * + * @author chemit + */ +public enum LanguageEnum { + + aa, // Afar + ab, // Abkhazian + af, // Afrikaans + am, // Amharic + ar, // Arabic + as, // Assamese + ay, // Aymara + az, // Azerbaijani + ba, // Bashkir + be, // Byelorussian + bg, // Bulgarian + bh, // Bihari + bi, // Bislama + bn, // Bengali; Bangla + bo, // Tibetan + br, // Breton + ca, // Catalan + co, // Corsican + cs, // Czech + cy, // Welsh + da, // Danish + de, // German + dz, // Bhutani + el, // Greek + en, // English + eo, // Esperanto + es, // Spanish + et, // Estonian + eu, // Basque + fa, // Persian + fi, // Finnish + fj, // Fiji + fo, // Faroese + fr, // French + fy, // Frisian + ga, // Irish + gd, // Scots Gaelic + gl, // Galician + gn, // Guarani + gu, // Gujarati + ha, // Hausa + he, // Hebrew (formerly iw) + hi, // Hindi + hr, // Croatian + hu, // Hungarian + hy, // Armenian + ia, // Interlingua + id, // Indonesian (formerly in) + ie, // Interlingue + ik, // Inupiak + is, // Icelandic + it, // Italian + iu, // Inuktitut + ja, // Japanese + jw, // Javanese + ka, // Georgian + kk, // Kazakh + kl, // Greenlandic + km, // Cambodian + kn, // Kannada + ko, // Korean + ks, // Kashmiri + ku, // Kurdish + ky, // Kirghiz + la, // Latin + ln, // Lingala + lo, // Laothian + lt, // Lithuanian + lv, // Latvian, Lettish + mg, // Malagasy + mi, // Maori + mk, // Macedonian + ml, // Malayalam + mn, // Mongolian + mo, // Moldavian + mr, // Marathi + ms, // Malay + mt, // Maltese + my, // Burmese + na, // Nauru + ne, // Nepali + nl, // Dutch + no, // Norwegian + oc, // Occitan + om, // (Afan) Oromo + or, // Oriya + pa, // Punjabi + pl, // Polish + ps, // Pashto, Pushto + pt, // Portuguese + qu, // Quechua + rm, // Rhaeto-Romance + rn, // Kirundi + ro, // Romanian + ru, // Russian + rw, // Kinyarwanda + sa, // Sanskrit + sd, // Sindhi + sg, // Sangho + sh, // Serbo-Croatian + si, // Sinhalese + sk, // Slovak + sl, // Slovenian + sm, // Samoan + sn, // Shona + so, // Somali + sq, // Albanian + sr, // Serbian + ss, // Siswati + st, // Sesotho + su, // Sundanese + sv, // Swedish + sw, // Swahili + ta, // Tamil + te, // Telugu + tg, // Tajik + th, // Thai + ti, // Tigrinya + tk, // Turkmen + tl, // Tagalog + tn, // Setswana + to, // Tonga + tr, // Turkish + ts, // Tsonga + tt, // Tatar + tw, // Twi + ug, // Uighur + uk, // Ukrainian + ur, // Urdu + uz, // Uzbek + vi, // Vietnamese + vo, // Volapuk + wo, // Wolof + xh, // Xhosa + yi, // Yiddish (formerly ji) + yo, // Yoruba + za, // Zhuang + zh, // Chinese + zu; // Zulu + + public static LanguageEnum valueOf(String language, LanguageEnum default= Value) { + LanguageEnum languageValue =3D null; + try { + languageValue =3D LanguageEnum.valueOf(language.toLowerCase()); + } catch (IllegalArgumentException e) { + System.err.println("Unfound language " + language + ", will use = default one " + defaultValue); + } catch (NullPointerException e) { + System.err.println("Unfound language " + language + ", will use = default one " + defaultValue); + } + return languageValue =3D=3D null ? defaultValue : languageValue; + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/Lang= uageEnum.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle= .java (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/i18n/= bundle/I18nBundle.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle.jav= a (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle.jav= a 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,154 @@ +/*=20 +* *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ +package org.nuiton.i18n.bundle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Class to represent a i18n Bundle. + *

+ * A bundle is defined by a resource prefix (eg /tmp/bundle.properties), and= a list of locale implemented entries. + *

+ * The property {@link #bundlePrefix} is the equals order property. + *

+ * The property {@link #entries} contains all entries defined for this bundl= e. + *

+ * The method {@link #getEntries(java.util.Locale)} filter entries for a giv= en locale, including scope inclusive property. + *

+ * The method {@link #getEntries(I18nBundleScope)} filter entries for a givn= e scope, with no inclusive logi. + *

+ * Thoses filter methods return result in the order defines in {@link I18nBu= ndleEntry}, e.g + *

+ * XXX.properties
+ * XXX-fr.properties
+ * XXX-fr_FR.properties
+ * 
+ * In that way, we can load resource in the good order : load before more ge= neral scope to more specialized. + * + * @author chemit + * @see I18nBundleScope + * @see I18nBundleEntry + */ +public class I18nBundle { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static final Log log =3D LogFactory.getLog(I18nBundle.class); + + /** les entr=C3=A9s du bundle */ + protected List entries; + + /** le nom du bundle encapsul=C3=A9 (correspond au prefix de l'url de ch= argement) */ + final String bundlePrefix; + + public I18nBundle(String bundlePrefix) { + this.bundlePrefix =3D bundlePrefix; + } + + public String getBundlePrefix() { + return bundlePrefix; + } + + /** + * Obtain the entries for a given locale, with a inclusive scope search. + *

+ * The order of result respect {@link I18nBundleEntry} order. + * + * @param locale the required locale + * @return the array of entries matching extacly the locale or one of th= e lesser scope one. + */ + public I18nBundleEntry[] getEntries(Locale locale) { + I18nBundleScope scope =3D I18nBundleScope.valueOf(locale); + + List result =3D new ArrayList(); + for (I18nBundleEntry entry : entries) { + I18nBundleScope i18nBundleScope =3D entry.getScope(); + // load from general to the max scope and always if there is onl= y one bundle entry found + if ((i18nBundleScope =3D=3D scope || i18nBundleScope.ordinal() <= scope.ordinal()) && entry.matchLocale(locale, scope)) { + result.add(entry); + } + } + return result.toArray(new I18nBundleEntry[result.size()]); + } + + /** + * Obtain the entries for a given scope + * The order of result respect {@link I18nBundleEntry} order. + * + * @param scope the required scope + * @return the list of entries matching exactly the given scope + */ + public I18nBundleEntry[] getEntries(I18nBundleScope scope) { + List result =3D new ArrayList(); + for (I18nBundleEntry entry : entries) { + I18nBundleScope i18nBundleScope =3D entry.getScope(); + // load from general to the max scope and always if there is onl= y one bundle entry found + if (i18nBundleScope =3D=3D scope) { + result.add(entry); + } + } + return result.toArray(new I18nBundleEntry[result.size()]); + } + + /** @return number of entries in bundle */ + public int size() { + return entries =3D=3D null ? 0 : entries.size(); + } + + @Override + public String toString() { + String s =3D super.toString(); + return "<" + s.substring(s.lastIndexOf(".") + 1) + ", bundlePrefix:"= + bundlePrefix + ", size:" + size() + ">"; + } + + protected List getEntries() { + return entries; + } + + protected boolean matchLocale(Locale locale) { + I18nBundleScope scope =3D I18nBundleScope.valueOf(locale); + boolean result =3D false; + if (size() !=3D 0) { + for (I18nBundleEntry entry : entries) { + if (entry.matchLocale(locale, scope)) { + result =3D true; + break; + } + } + } + return result; + } + + protected boolean addEntry(I18nBundleEntry entry) { + if (entries =3D=3D null) { + entries =3D new ArrayList(); + } + boolean b =3D entries.add(entry); + if (log.isDebugEnabled()) { + log.info(this + "\n\t" + entry); + } + return b; + } + + +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bund= le/I18nBundle.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle= Entry.java (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/= i18n/bundle/I18nBundleEntry.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleEntr= y.java (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleEntr= y.java 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,192 @@ +/*=20 + * *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ +package org.nuiton.i18n.bundle; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.Properties; +import org.nuiton.i18n.I18nUtil; +import org.nuiton.i18n.I18nFileReader; + +/** + * A class to represent an entry in a bundle. + *

+ * The object matches exactly one resource file in a given scope. + *

+ * The object has three properties : + *

    + *
  • {@link #path} : the path to resource file where to find transaltion = for the entry. + *
  • {@link #locale} : the locale of the entry + *
  • {link #scope} ; the scope of the entry + *
+ * This object defines a equals order base on property {@link #path}. + *

+ * This object is {@link Comparable}, the order relation is defined like thi= s : + *

    + *
  • sort first on {@link #scope}, in the scope order (see {@link I18nBun= dleScope}), + *
  • if scopes are equals, sort on {@link #locale} string representation. + *
+ * + * @author chemit + * @see I18nBundleScope + */ +public class I18nBundleEntry implements Comparable { + + /** path to resource file */ + protected URL path; + /** local of the entry, can be null if general scope */ + protected Locale locale; + /** scope of the entry */ + protected I18nBundleScope scope; + + /** + * Constructor if an bundle entry. + *

+ * It is defined by a path of the resource file, a scope an= d a locale. + * + * @param path the path of the resource file fo the bundle entry + * @param locale the given locale of the bundle entry + * @param scope the scope of the given entry + */ + public I18nBundleEntry(URL path, Locale locale, I18nBundleScope scope) { + this.path =3D path; + this.locale =3D locale; + this.scope =3D scope; + } + + public URL getPath() { + return path; + } + + public Locale getLocale() { + return locale; + } + + public I18nBundleScope getScope() { + return scope; + } + + /** + * Method to match or not a bundle entry for a given scope and locale. + *

+ * We use the inclusive property of scope, means that we accept all entr= ies on the path + * to the generalest entry for a givne locale. + * + * @param locale the locale to match + * @param scope the highest scope to match + * @return true if the entry match the scope and locale + * * + */ + public boolean matchLocale(Locale locale, I18nBundleScope scope) { + if (this.locale =3D=3D null) { + // a general bundle entry is always matched! + return true; + } + if (locale =3D=3D null) { + // can not match a specialized entry with a general scope + return false; + } + // match full locale, or at least a language=20 + return this.locale.equals(locale) || + (this.scope.ordinal() < scope.ordinal() && locale.getLanguag= e().equals(this.locale.getLanguage())); + } + + /** + * For a given language, load the resource file of this entry into the <= code>resource + * properties object. + * + * @param resource the save of resources already loaded + * @throws IOException if any pb while reading resource file + */ + public void load(Properties resource) throws IOException { + InputStream inputStream =3D null; + StringBuilder sb =3D new StringBuilder(); + try { + I18nFileReader fileReader =3D new I18nFileReader(); + inputStream =3D getPath().openStream(); + //String encoding =3D language.getEncoding(); + if (I18nBundle.log.isDebugEnabled()) { + sb.append(getPath()).append("\n"); + } + // TC 20081117 always use ISO_8859_1_ENCONDING, since java does = it like this. =20 + fileReader.load(inputStream, I18nUtil.ISO_8859_1_ENCONDING); + + if (I18nBundle.log.isDebugEnabled()) { + for (Entry entry : fileReader.entrySet()) { + sb.append(I18nUtil.ISO_8859_1_ENCONDING).append(" : ").a= ppend(entry).append("\n"); + } + } + for (Entry entry : fileReader.entrySet()) { + String key =3D (String) entry.getKey(); + String value =3D (String) entry.getValue(); + if (value.trim().isEmpty()) { + // if there is a previous sentence loaded but not empty + // do not override it + String oldValue =3D (String) resource.get(key); + if (oldValue !=3D null) { + continue; + } + } + resource.put(key, value); + } + //resource.putAll(fileReader); + if (I18nBundle.log.isDebugEnabled()) { + sb.append("nbSentences : ").append(fileReader.size()).append= ("\n"); + sb.append("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D"); + } + fileReader.clear(); + + } finally { + if (I18nBundle.log.isDebugEnabled()) { + I18nBundle.log.debug(sb.toString()); + } + if (inputStream !=3D null) { + inputStream.close(); + } + } + } + + @Override + public int compareTo(I18nBundleEntry o) { + int i =3D getScope().compareTo(o.getScope()); + if (i =3D=3D 0) { + // same scope, sort on locale + i =3D getLocale().toString().compareTo(o.getLocale().toString()); + } + return i; + } + + @Override + public boolean equals(Object o) { + return this =3D=3D o || o instanceof I18nBundleEntry && path.equals(= ((I18nBundleEntry) o).path); + } + + @Override + public int hashCode() { + return path.hashCode(); + } + + @Override + public String toString() { + String s =3D super.toString(); + return "<" + s.substring(s.lastIndexOf(".") + 1) + ", locale:" + loc= ale + ", scope " + scope + ", path:" + path + ">"; + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bund= le/I18nBundleEntry.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle= Factory.java (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codeluti= n/i18n/bundle/I18nBundleFactory.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleFact= ory.java (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleFact= ory.java 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,548 @@ +package org.nuiton.i18n.bundle; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18nUtil; + +/** + * Classe qui est responsable de la detection et construction + * de {@link I18nBundle}. + * + * On retrouve aussi ici des m=C3=A9thodes utiles de parcours de bundles. + * + * @author chemit + * + * @since 1.0.6 + */ +public class I18nBundleFactory { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log =3D LogFactory.getLog(I18nBundleFactory.cla= ss); + /** pattern to find all i18n bundles in classloader class path */ + public static final String SEARCH_BUNDLE_PATTERN =3D ".*i18n/.+\\.proper= ties"; + public static final String DIRECTORY_SEARCH_BUNDLE_PATTERN =3D "i18n"; + protected static String UNIQUE_BUNDLE_PATH =3D "/META-INF/"; + public static String UNIQUE_BUNDLE_DEF =3D "%1$s-definition.properties"; + public static String UNIQUE_BUNDLE_ENTRY =3D "%1$s-%2$s.properties"; + public static String BUNDLE_DEF_LOCALES =3D "locales"; + + /** + * R=C3=A9cuperation de toutes les locales connus par un ensemble de bun= dles. + *=20 + * @param bundles les bundles a parcourir + * @return la liste des locales rencontr=C3=A9es + */ + public static Locale[] getLocales(I18nBundle... bundles) { + Set result =3D new java.util.HashSet(); + for (I18nBundle i18nBundle : bundles) { + for (I18nBundleEntry entry : i18nBundle.getEntries()) { + Locale o =3D entry.getLocale(); + if (o !=3D null) { + result.add(o); + } + } + } + return result.toArray(new Locale[result.size()]); + } + + /** + * Filtrage des bundles qui correspondante =C3=A0 la locale donn=C3=A9e. + * + * @param l la locale =C3=A0 filtrer + * @param bundles les bundles a parcourir + * @return les bundles qui correspondent =C3=A0 la locale donn=C3=A9e. + */ + public static I18nBundle[] getBundles(Locale l, I18nBundle... bundles) { + List result =3D new ArrayList(); + for (I18nBundle i18nBundle : bundles) { + if (i18nBundle.matchLocale(l)) { + result.add(i18nBundle); + } + } + return result.toArray(new I18nBundle[result.size()]); + } + + /** + * R=C3=A9cup=C3=A9ration de toutes les entr=C3=A9es de bundles pour les= bundles donn=C3=A9es. + * + * @param bundles les bundles a parcourir + * @return toutes les entr=C3=A9es de bundles. + */ + public static I18nBundleEntry[] getBundleEntries(I18nBundle... bundles) { + List result =3D new ArrayList(); + for (I18nBundle i18nBundle : bundles) { + List list =3D i18nBundle.getEntries(); + if (!list.isEmpty()) { + result.addAll(list); + } + } + return result.toArray(new I18nBundleEntry[result.size()]); + } + + /** + * Filtrage des entr=C3=A9es de bundles pour une locale donn=C3=A9e. + * + * On essaye de trouver les meilleurs entr=C3=A9es possibles (possibilit= =C3=A9 de + * promotion). + * + * Note: Cette m=C3=A9thode doit =C3=AAtre utilis=C3=A9 pour trouver tou= tes les entr=C3=A9es =C3=A0 + * charger par le syst=C3=A8me i18n pour une locale donn=C3=A9e. + * + * @param l la locale =C3=A0 filtrer + * @param defaultLocale la locale =C3=A0 utiliser pour les promotions + * @param bundles les bundles a parcourir + * @return les entr=C3=A9es de bundles filtr=C3=A9s. + */ + public static I18nBundleEntry[] getBundleEntries(Locale l, Locale defaul= tLocale, I18nBundle... bundles) { + + List result =3D new ArrayList(); + for (I18nBundle i18nBundle : bundles) { + I18nBundleEntry[] entries =3D i18nBundle.getEntries(l); + if (entries.length =3D=3D 0) { + //no entry found for the bundle, try pomotion + entries =3D promuteBundle(i18nBundle, l, defaultLocale); + } + result.addAll(Arrays.asList(entries)); + } + return result.toArray(new I18nBundleEntry[result.size()]); + } + + /** + * Teste si un ensemble de bundles contient au moins une entr=C3=A9e. + * + * @param bundles les bundles a parcourir + * @return true si aucune entree trouvee, false + * autrement. + */ + public static boolean isEmpty(I18nBundle... bundles) { + for (I18nBundle i18nBundle : bundles) { + if (!i18nBundle.getEntries().isEmpty()) { + // on a trouve au moins une entree + return false; + } + } + return true; + } + + /** + * Recherche la liste des url de toutes les resources i18n, i.e les urls + * des fichiers de traduction en mode uniqueBundleName. + * + * On va d'abord rechercher un fichier /META-INF/unqiueBundleName-defini= tion.properties + * + * Dans ce fichier il y a une entree locales qui contient les locales du= bundle + * + * Ensuite pour chaque locale on recupere l'url du fichier : + * + * /META-INF/uniqueBundleName-locale.properties + * + * @param uniqueBundleName le nom de lu'inque bundle a charger + * @return la liste des urls de bundle i18n + */ + public static URL[] getURLs(String uniqueBundleName) { + + String definitionFileName =3D String.format(UNIQUE_BUNDLE_DEF, uniqu= eBundleName); + URL[] urls =3D null; + + try { + URL defURL =3D I18nBundleFactory.class.getResource(UNIQUE_BUNDLE= _PATH + definitionFileName); + log.info("definition i18n file : " + defURL); + InputStream stream =3D defURL.openStream(); + Properties p =3D new Properties(); + p.load(stream); + stream.close(); + + String localesAsStr =3D p.getProperty(BUNDLE_DEF_LOCALES); + Locale[] locales =3D I18nUtil.parseLocales(localesAsStr); + List lUrls =3D new java.util.ArrayList(1); + String prefixURL =3D defURL.toString(); + prefixURL =3D prefixURL.substring(0, prefixURL.length() - defini= tionFileName.length()); + //FIXME on devrait tester que la resource est disponible ? + + for (Locale l : locales) { + String url =3D prefixURL + String.format(UNIQUE_BUNDLE_ENTRY= , uniqueBundleName, l.toString()); + log.info("detected bundle properties file : " + url); + URL u =3D new URL(url); +// //FIXME on devrait tester que la resource est disponible ? + + lUrls.add(u); + } + if (!lUrls.isEmpty()) { + urls =3D lUrls.toArray(new URL[lUrls.size()]); + } else { + // l'unique bundle n'a pas ete trouve! + // on utilise la methode classique de chargement avec recher= che + // de tous les bundles i18n + log.warn("not bundle files detected in " + prefixURL); + urls =3D null; + } + + } catch (Exception ex) { + log.warn("could not load unique bundle " + uniqueBundleName + " = for reason " + ex.getMessage(), ex); + urls =3D null; + + } + return urls; + } + + /** + * Recherche la liste des url de toutes les resources i18n, i.e les urls + * des fichiers de traduction. + * + * @param urls des urls de resources i18n deja calcule, =C3=A0 ajouter a= u resultat sans traitement particulier + * @return la liste des urls de bundle i18n + */ + public static URL[] getURLs(URL... urls) { + + try { + // on calcule toutes les urls utilisable dans le classloader don= nee + List urlToSeek =3D new ArrayList(); + urlToSeek.addAll(Arrays.asList(urls)); + + // on va maintenant supprimer toutes les urls qui ne respectent = pas + // le pattern i18n : il faut que la resource contienne un repert= oire i18n + // ce simple test permet de restreindre la recherche des resourc= es + // i18n qui est tres couteuse + int size =3D urlToSeek.size(); + for (Iterator it =3D urlToSeek.iterator(); it.hasNext();) { + URL url =3D it.next(); + if (!I18nUtil.containsDirectDirectory(url, DIRECTORY_SEARCH_= BUNDLE_PATTERN)) { + if (log.isDebugEnabled()) { + log.debug("skip url with no " + DIRECTORY_SEARCH_BUN= DLE_PATTERN + " directory : " + url); + } + it.remove(); + } + } + + if (log.isDebugEnabled()) { + log.debug("detect " + urlToSeek.size() + " i18n capable url = (out of " + size + ")"); + } + + List listURLs =3D new java.util.ArrayList(); + + for (URL url : urlToSeek) { + // on recherche tous les fichiers de traduction pour cet url + + List result =3D null; + + if (log.isDebugEnabled()) { + log.debug("seek in : " + url); + } + + String fileName =3D url.getFile(); + // TODO deal with encoding in windows, this is very durty, b= ut it + // works... + File file =3D new File(fileName.replaceAll("%20", " ")); + + if (I18nUtil.isJar(fileName)) { + // cas ou le ichier du classLoader est un fichier jar + if (log.isDebugEnabled()) { + log.debug("jar to search " + file); + } + result =3D getURLsFromJar(url, file); + + } else if (file.isDirectory()) { + // cas ou le ichier du classLoader est un repertoire + if (log.isDebugEnabled()) { + log.debug("directory to search " + file); + } + // on traite le cas ou il peut y avoir des repertoire da= ns ce + // repertoire + result =3D getURLsFromDirectory(url, file); + } + if (result !=3D null && !result.isEmpty()) { + listURLs.addAll(result); + } + + } + return listURLs.toArray(new URL[listURLs.size()]); + } catch (Exception eee) { + log.warn("Unable to find urls for urls : " + urls + " for reason= " + eee.getMessage(), eee); + return new URL[0]; + } + } + + /** + * Detecte les bundles i18n a partir des urls des fichiers de traduction + * donnes. + * + * Tous les entr=C3=A9es de bundles sont triees dans l'ordre des scopes = i18n. + * + * @param urls les urls des fichiers de traductions + * @return la liste des bundle i18n construits =C3=A0 partir des fichier= s de + * traduction donnes. + */ + public static List detectBundles(URL... urls) { + + List bundleNames =3D new ArrayList(); + List bundles =3D new ArrayList(); + + for (URL url : urls) { + + if (addBundleEntry(url, I18nBundleScope.FULL, bundleNames, bundl= es)) { + // found a full bundle + continue; + } + if (addBundleEntry(url, I18nBundleScope.LANGUAGE, bundleNames, b= undles)) { + // found a language bundle + continue; + } + // must be a general bundle with no locale defined + addBundleEntry(url, I18nBundleScope.GENERAL, bundleNames, bundle= s); + } + bundleNames.clear(); + + // once for all, sort entries from general to full + for (I18nBundle bundle : bundles) { + java.util.Collections.sort(bundle.getEntries()); + } + =20 + return bundles; + } + + protected static boolean addBundleEntry(URL url, I18nBundleScope scope, = List bundleNames, List bundles) { + String path =3D url.toString(); + Matcher matcher =3D scope.getMatcher(path); + if (!matcher.matches()) { + // no match at this scope + return false; + } + // create a new bundle entry + I18nBundleEntry entry =3D new I18nBundleEntry(url, scope.getLocale(m= atcher), scope); + if (log.isDebugEnabled()) { + log.debug("bundle (" + bundles.size() + ") : " + entry); + } + // get the associated bundle + I18nBundle bundle =3D addBundle(scope.getBundlePrefix(matcher), bund= leNames, bundles); + // add entry to bundle + bundle.addEntry(entry); + return true; + } + + protected static I18nBundle addBundle(String bundleName, List bu= ndleNames, List bundles) { + I18nBundle bundle; + int index =3D bundleNames.indexOf(bundleName); + if (index > -1) { + bundle =3D bundles.get(index); + } else { + bundle =3D new I18nBundle(bundleName); + if (log.isDebugEnabled()) { + log.debug("bundle (" + bundles.size() + ") : " + bundle); + } + bundles.add(bundle); + bundleNames.add(bundleName); + } + return bundle; + } + + /** + * Obtain some rescue entries for a given locale. + *

+ * Note: Calling this method implies there is no entry matched by the= common method + * {@link #getBundleEntries(Locale, Locale, I18nBundle[])} return a empt= y array. + * + * @param bundle the bundle to promute + * @param l the locale required + * @param defaultLocale the default locale to used for promotion + * @return the table of entries promuted for the given locale + */ + protected static I18nBundleEntry[] promuteBundle(I18nBundle bundle, Loca= le l, Locale defaultLocale) { + + I18nBundleScope scope =3D I18nBundleScope.valueOf(l); + + if (log.isDebugEnabled()) { + log.debug('[' + bundle.getBundlePrefix() + "] did not find match= ing entries for locale " + l + ". Try to detect best entries..."); + } + + if (bundle.size() =3D=3D 0) { + // there is no entry to take... + log.warn("PROMUTE NO ENTRY FOUND"); + return new I18nBundleEntry[0]; + } + + if (bundle.size() =3D=3D 1) { + // there is one entry take it,what ever... + I18nBundleEntry entry =3D bundle.getEntries().get(0); + log.warn("PROMUTE" + l + " to " + entry.getLocale() + " [" + bun= dle.getBundlePrefix() + ']'); + return new I18nBundleEntry[]{entry}; + } + + List result =3D new ArrayList(); + + switch (scope) { + case FULL: + promuteFull(bundle, l, defaultLocale, result); + break; + case LANGUAGE: + promuteLanguage(bundle, l, defaultLocale, result); + break; + case GENERAL: + promuteGeneral(bundle, l, defaultLocale, result); + break; + } + return result.toArray(new I18nBundleEntry[result.size()]); + } + + protected static void promuteFull(I18nBundle bundle, Locale locale, Loca= le defaultLocale, List result) { + if (bundle.size() =3D=3D 0) { + return; + } + // try with a another FULL matching locale ? + for (I18nBundleEntry entry : bundle.getEntries()) { + I18nBundleScope i18nBundleScope =3D entry.getScope(); + // load from general to the max scope and always if there is onl= y one bundle entry found + if (i18nBundleScope =3D=3D I18nBundleScope.FULL && + !entry.getLocale().getCountry().equals(locale.getCountry= ()) && + entry.getLocale().getLanguage().equals(locale.getLanguag= e())) { + log.warn(locale + " to " + entry.getLocale() + " [" + bundle= .getBundlePrefix() + ']'); + result.add(entry); + // we take the first one, this is a resuce!!! + break; + } + } + if (result.isEmpty()) { + // full promotion failed,trylanguage promotion + promuteLanguage(bundle, locale, defaultLocale, result); + } + + } + + protected static void promuteLanguage(I18nBundle bundle, Locale locale, = Locale defaultLocale, List result) { + if (bundle.size() =3D=3D 0) { + return; + } + for (I18nBundleEntry entry : bundle.getEntries()) { + I18nBundleScope i18nBundleScope =3D entry.getScope(); + // load from general to the max scope and always if there is onl= y one bundle entry found + if (i18nBundleScope =3D=3D I18nBundleScope.FULL && entry.getLoca= le().getLanguage().equals(locale.getLanguage())) { + result.add(entry); + log.warn(locale + " to " + entry.getLocale() + " [" + bundle= .getBundlePrefix() + ']'); + // we take the first one, this is a resuce!!! + break; + } + } + if (result.isEmpty()) { + // language promotion failed,try general promotion + promuteGeneral(bundle, locale, defaultLocale, result); + } + } + + protected static void promuteGeneral(I18nBundle bundle, Locale locale, L= ocale defaultLocale, List result) { + if (bundle.size() =3D=3D 0) { + return; + } + if (bundle.size() =3D=3D 1) { + // there is one entry take it,what ever... + I18nBundleEntry entry =3D bundle.getEntries().get(0); + result.add(entry); + log.warn(locale + " to " + entry.getLocale() + " [" + bundle.get= BundlePrefix() + ']'); + return; + } + I18nBundleScope scope =3D I18nBundleScope.valueOf(defaultLocale); + for (I18nBundleEntry entry : bundle.getEntries(scope)) { + if (entry.getLocale().equals(defaultLocale)) { + // default locale found + log.warn(locale + " to " + entry.getLocale() + " [" + bundle= .getBundlePrefix() + ']'); + result.add(entry); + return; + } + } + + // default locale not found, take the first one ? + I18nBundleEntry entry =3D bundle.getEntries().get(0); + result.add(entry); + log.warn(locale + " to " + entry.getLocale() + " [" + bundle.getBund= lePrefix() + ']'); + //TODO Should try to load default en_GB from I18nLoader ? + //I18n.DEFAULT_LOCALE.getCountry() + } + + protected static List getURLsFromJar(URL incomingURL, File jarfile)= { + + String pattern =3D SEARCH_BUNDLE_PATTERN; + try { + + List result =3D new ArrayList(); + InputStream in =3D new FileInputStream(jarfile); + ZipInputStream zis =3D new ZipInputStream(in); + ClassLoader cl =3D new URLClassLoader(new URL[]{incomingURL}, I1= 8nBundleFactory.class.getClassLoader()); + while (zis.available() !=3D 0) { + ZipEntry entry =3D zis.getNextEntry(); + + if (entry =3D=3D null) { + break; + } + + String name =3D entry.getName(); + + if (pattern =3D=3D null || name.matches(pattern)) { + // on recupere le fichier correspondant au pattern dans = le + // classloader + if (log.isDebugEnabled()) { + log.debug(name + " accepted for pattern " + pattern); + } + URL url =3D cl.getResource(name); + // on ajoute le fichier correspondant au pattern dans la + // liste + result.add(url); + } + } + + return result; + } catch (Exception eee) { + throw new RuntimeException("n'a pas pu trouve la resource dans l= e jar " + jarfile.getAbsolutePath(), eee); + } + } + + protected static List getURLsFromDirectory(URL incomingURL, File re= pository) { + String pattern =3D SEARCH_BUNDLE_PATTERN; + try { + if (log.isDebugEnabled()) { + log.debug("search '" + pattern + "' in " + repository); + } + + List urlList =3D new ArrayList(); + File[] filesList =3D repository.listFiles(); + + if (filesList !=3D null) { + + for (File file : filesList) { + + String name =3D file.getAbsolutePath(); + + // cas de recursivite : repertoire dans un repertoire + if (file.exists() && file.isDirectory()) { + urlList.addAll(I18nUtil.getURLsFromDirectory(file, + pattern)); + // si le fichier du repertoire n'est pas un repertoi= re + // on verifie s'il correspond au pattern + } else if (pattern =3D=3D null || name.matches(pattern))= { + URL url =3D file.toURI().toURL(); + if (log.isDebugEnabled()) { + log.debug("directory: " + repository + " url: " = + url); + } + urlList.add(url); + } + } + } + return urlList; + } catch (MalformedURLException eee) { + throw new RuntimeException("n'a pas pu trouve la resource dans l= e repertoire " + repository.getAbsolutePath(), eee); + } + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bund= le/I18nBundleFactory.java ___________________________________________________________________ Name: svn:mergeinfo +=20 Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundle= Scope.java (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/= i18n/bundle/I18nBundleScope.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleScop= e.java (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bundle/I18nBundleScop= e.java 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,144 @@ +/*=20 +* *##% Lutin utilities library + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ +package org.nuiton.i18n.bundle; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.nuiton.i18n.I18nUtil; + +/** + * The enumaration defines the scope of a bundle entry. + *

+ * There is three scope possible: + *

    + *
  • {@link #GENERAL} : for a bundle entry with no locale specialized info= rmation, eg : bundle.properties
  • + *
  • {@link #LANGUAGE} : for a bundle entry with language locale specializ= ed information, eg : bundle-en.properties
  • + *
  • {@link #FULL} : for a bundle entry with full locale specialized infor= mation, eg : bundle-en_GB.properties
  • + *
+ *

+ * We define a order relation, from general to full scope : + *

+ * {@link #GENERAL} < {@link #LANGUAGE} < {@link #FULL} + *

+ * Scopes are inclusives, in a search of entries, eg the search of en_= GB will include en scope... + *

+ * The {@link #patternAll} is the searching pattern of bundle of the scope. + *

+ * The method {@link #getMatcher(String)} obtain from the {@link #patternAl= l} the matcher for a bundle path. + *

+ * The method {@link #getLocale(Matcher)} obtain from the {@link #patternAll= } matched in a bundle path, the + * corresponding locale. + *

+ * The class offer also a static method {@link #valueOf(java.util.Locale)} = to obtain the scope of a locale. + * + * @author chemit + */ +public enum I18nBundleScope { + + /** default scope (with no language, nor country information) */ +// GENERAL("(.*18n/.+)\\.properties") { + GENERAL("(.*/.+)\\.properties") { + @Override + public Locale getLocale(Matcher matcher) { + // no locale for general bundle =20 + return null; + } + }, + + /** language scope (no country information) */ +// LANGUAGE("(.*18n/.+)-(\\w\\w)\\.properties") { + LANGUAGE("(.*/.+)-(\\w\\w)\\.properties") { + @Override + public Locale getLocale(Matcher matcher) { + Locale result =3D null; + if (matcher.matches()) { + result =3D I18nUtil.newLocale(matcher.group(2)); + } + return result; + } + }, + + /** full scope : language + country */ +// FULL("(.*18n/.+)-(\\w\\w_\\w\\w)\\.properties") { + FULL("(.*/.+)-(\\w\\w_\\w\\w)\\.properties") { + @Override + public Locale getLocale(Matcher matcher) { + Locale result =3D null; + if (matcher.matches()) { + result =3D I18nUtil.newLocale(matcher.group(2)); + } + return result; + } + }; + + /** pattern used to detect bundle entry */ + private final Pattern patternAll; + + /** + * Obtain the scope of a given locale. + *

+ * The given locale can be null, which means {@link I18nBundleScope#GENE= RAL} scope. + * + * @param locale given locale to convert + * @return the scope of given locale + */ + public static I18nBundleScope valueOf(Locale locale) { + if (locale =3D=3D null || locale.getLanguage() =3D=3D null || locale= .getLanguage().length() =3D=3D 0) { + return GENERAL; + } + if (locale.getCountry() =3D=3D null || locale.getCountry().length() = =3D=3D 0) { + return LANGUAGE; + } + return FULL; + } + + /** + * get a matcher fro the given path for this scope + * + * @param path the path to treate + * @return the bunle detect matcher + */ + public Matcher getMatcher(String path) { + return patternAll.matcher(path); + } + + /** + * get the locale for a given matcher. + * + * @param matcher the scope matcher to use + * @return the locale + */ + public abstract Locale getLocale(Matcher matcher); + + /** + * @param matcher the scope matcher to use + * @return the prefix of the bundle + */ + public String getBundlePrefix(Matcher matcher) { + String result =3D null; + if (matcher.matches()) { + result =3D matcher.group(1); + } + return result; + } + + private I18nBundleScope(String patternAll) { + this.patternAll =3D Pattern.compile(patternAll); + } +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/i18n/bund= le/I18nBundleScope.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native Copied: nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/LocaleConverter.j= ava (from rev 1542, nuiton-i18n-api/trunk/src/main/java/org/codelutin/util/Lo= caleConverter.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/LocaleConverter.java = (rev 0) +++ nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/LocaleConverter.java = 2009-05-14 05:41:01 UTC (rev 1550) @@ -0,0 +1,122 @@ +/*=20 + * *##% Lutin utilities library + * Copyright (C) 2004 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . ##%* */ + +package org.nuiton.util; + +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.beanutils.Converter; +import static org.apache.commons.logging.LogFactory.getLog; +import org.nuiton.i18n.CountryEnum; +import org.nuiton.i18n.LanguageEnum; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * classe pour convertir une chaine en un objet {@link java.util.Locale}. + * + * @author chemit + */ +public class LocaleConverter implements Converter { + + private static final Pattern FULL_SCOPE_PATTERN =3D Pattern.compile("([a= -zA-Z]{2})_([a-zA-Z]{2})"); + + private static final Pattern MEDIUM_SCOPE_PATTERN =3D Pattern.compile("(= [a-zA-Z]{2})"); + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static org.apache.commons.logging.Log log =3D getLog(LocaleConverter.cla= ss); + + public Object convert(Class aClass, Object value) { + if (value =3D=3D null) { + throw new ConversionException("can not convert null value in " += this + " convertor"); + } + if (isEnabled(aClass)) { + Object result; + if (isEnabled(value.getClass())) { + result =3D value; + return result; + } + if (value instanceof String) { + result =3D valueOf(((String) value).trim()); + return result; + } + } + throw new ConversionException("could not find a convertor for type "= + aClass.getName() + " and value : " + value); + } + + protected Locale valueOf(String value) { + try { + Locale result =3D convertFullScope(value); + + if (result =3D=3D null) { + result =3D convertMediumScope(value); + } + + if (result =3D=3D null) { + throw new ConversionException("could not convert locale " + = value); + } + + return result; + } catch (Exception e) { + throw new ConversionException("could not convert locale " + valu= e + " for reason " + e.getMessage()); + } + } + + private Locale convertFullScope(String value) { + Matcher m =3D FULL_SCOPE_PATTERN.matcher(value); + if (m.matches()) { + // found a full scope pattern (language + country) + LanguageEnum language =3D LanguageEnum.valueOf(m.group(1).toLowe= rCase()); + CountryEnum country =3D CountryEnum.valueOf(m.group(2).toUpperCa= se()); + if (language =3D=3D null || country =3D=3D null) { + // not safe + throw new ConversionException("could not convert locale " + = value); + } + return new Locale(language.name(), country.name()); + } + return null; + } + + private Locale convertMediumScope(String value) { + Matcher m =3D MEDIUM_SCOPE_PATTERN.matcher(value); + if (m.matches()) { + // found a medium scope pattern (only language) + LanguageEnum language =3D LanguageEnum.valueOf(m.group(1).toLowe= rCase()); + + if (language =3D=3D null) { + // not safe + throw new ConversionException("could not convert locale " + = value); + } + return new Locale(language.name()); + } + return null; + } + + + public LocaleConverter() { + if (log.isDebugEnabled()) { + log.debug(this); + } + } + + protected boolean isEnabled(Class aClass) { + return aClass =3D=3D Locale.class; + } + +} Property changes on: nuiton-i18n-api/trunk/src/main/java/org/nuiton/util/Loca= leConverter.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:mergeinfo +=20 Name: svn:eol-style + native --===============7267657007204645654==--