Codebase list liblocales-perl / fresh-snapshots/main
New upstream snapshot. Debian Janitor 1 year, 3 months ago
11 changed file(s) with 2536 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
00 Revision history for Perl distribution Locales
1
2 0.35 ???
3 - Add meta-spec versions 2 stuff to aid in metacpan indexing
4 - prompted by rt 125178 (needed reindexed in PAUSE), thx for the report TODDR!
5 - change bug tracker to github
16
27 0.34 2016-01-15 16:07:01
38 - Add v0.33 tests to the .in file
0 _build/_locales_build_utils.pm
1 _build/cldr2locales
2 _build/cldr2en
3 _build/en2mod
4 _build/README
05 Changes
16 Makefile.PL
27 MANIFEST
867872 lib/Locales/DB/LocaleDisplayPattern/Tiny.pm
868873 lib/Locales/DB/Docs/PluralForms.pm
869874 lib/Locales/DB/Loadable.pm
875 share/misc_info/aa.js
876 share/code_to_name/aa.json
877 share/datetime/aa.json
878 share/functions/aa.js
879 share/misc_info/af.js
880 share/code_to_name/af.json
881 share/datetime/af.json
882 share/functions/af.js
883 share/misc_info/agq.js
884 share/code_to_name/agq.json
885 share/datetime/agq.json
886 share/functions/agq.js
887 share/misc_info/ak.js
888 share/code_to_name/ak.json
889 share/datetime/ak.json
890 share/functions/ak.js
891 share/misc_info/am.js
892 share/code_to_name/am.json
893 share/datetime/am.json
894 share/functions/am.js
895 share/misc_info/ar.js
896 share/code_to_name/ar.json
897 share/datetime/ar.json
898 share/functions/ar.js
899 share/misc_info/as.js
900 share/code_to_name/as.json
901 share/datetime/as.json
902 share/functions/as.js
903 share/misc_info/asa.js
904 share/code_to_name/asa.json
905 share/datetime/asa.json
906 share/functions/asa.js
907 share/misc_info/az.js
908 share/code_to_name/az.json
909 share/datetime/az.json
910 share/functions/az.js
911 share/misc_info/bas.js
912 share/code_to_name/bas.json
913 share/datetime/bas.json
914 share/functions/bas.js
915 share/misc_info/be.js
916 share/code_to_name/be.json
917 share/datetime/be.json
918 share/functions/be.js
919 share/misc_info/bem.js
920 share/code_to_name/bem.json
921 share/datetime/bem.json
922 share/functions/bem.js
923 share/misc_info/bez.js
924 share/code_to_name/bez.json
925 share/datetime/bez.json
926 share/functions/bez.js
927 share/misc_info/bg.js
928 share/code_to_name/bg.json
929 share/datetime/bg.json
930 share/functions/bg.js
931 share/misc_info/bm.js
932 share/code_to_name/bm.json
933 share/datetime/bm.json
934 share/functions/bm.js
935 share/misc_info/bn.js
936 share/code_to_name/bn.json
937 share/datetime/bn.json
938 share/functions/bn.js
939 share/misc_info/bo.js
940 share/code_to_name/bo.json
941 share/datetime/bo.json
942 share/functions/bo.js
943 share/misc_info/br.js
944 share/code_to_name/br.json
945 share/datetime/br.json
946 share/functions/br.js
947 share/misc_info/brx.js
948 share/code_to_name/brx.json
949 share/datetime/brx.json
950 share/functions/brx.js
951 share/misc_info/bs.js
952 share/code_to_name/bs.json
953 share/datetime/bs.json
954 share/functions/bs.js
955 share/misc_info/byn.js
956 share/code_to_name/byn.json
957 share/datetime/byn.json
958 share/functions/byn.js
959 share/misc_info/ca.js
960 share/code_to_name/ca.json
961 share/datetime/ca.json
962 share/functions/ca.js
963 share/misc_info/cch.js
964 share/code_to_name/cch.json
965 share/datetime/cch.json
966 share/functions/cch.js
967 share/misc_info/cgg.js
968 share/code_to_name/cgg.json
969 share/datetime/cgg.json
970 share/functions/cgg.js
971 share/misc_info/chr.js
972 share/code_to_name/chr.json
973 share/datetime/chr.json
974 share/functions/chr.js
975 share/misc_info/cs.js
976 share/code_to_name/cs.json
977 share/datetime/cs.json
978 share/functions/cs.js
979 share/misc_info/cy.js
980 share/code_to_name/cy.json
981 share/datetime/cy.json
982 share/functions/cy.js
983 share/misc_info/da.js
984 share/code_to_name/da.json
985 share/datetime/da.json
986 share/functions/da.js
987 share/misc_info/dav.js
988 share/code_to_name/dav.json
989 share/datetime/dav.json
990 share/functions/dav.js
991 share/misc_info/de.js
992 share/code_to_name/de.json
993 share/datetime/de.json
994 share/functions/de.js
995 share/misc_info/de_at.js
996 share/code_to_name/de_at.json
997 share/datetime/de_at.json
998 share/functions/de_at.js
999 share/misc_info/de_ch.js
1000 share/code_to_name/de_ch.json
1001 share/datetime/de_ch.json
1002 share/functions/de_ch.js
1003 share/misc_info/dje.js
1004 share/code_to_name/dje.json
1005 share/datetime/dje.json
1006 share/functions/dje.js
1007 share/misc_info/dua.js
1008 share/code_to_name/dua.json
1009 share/datetime/dua.json
1010 share/functions/dua.js
1011 share/misc_info/dyo.js
1012 share/code_to_name/dyo.json
1013 share/datetime/dyo.json
1014 share/functions/dyo.js
1015 share/misc_info/dz.js
1016 share/code_to_name/dz.json
1017 share/datetime/dz.json
1018 share/functions/dz.js
1019 share/misc_info/ebu.js
1020 share/code_to_name/ebu.json
1021 share/datetime/ebu.json
1022 share/functions/ebu.js
1023 share/misc_info/ee.js
1024 share/code_to_name/ee.json
1025 share/datetime/ee.json
1026 share/functions/ee.js
1027 share/misc_info/el.js
1028 share/code_to_name/el.json
1029 share/datetime/el.json
1030 share/functions/el.js
1031 share/misc_info/en.js
1032 share/code_to_name/en.json
1033 share/datetime/en.json
1034 share/functions/en.js
1035 share/misc_info/en_au.js
1036 share/code_to_name/en_au.json
1037 share/datetime/en_au.json
1038 share/functions/en_au.js
1039 share/misc_info/en_ca.js
1040 share/code_to_name/en_ca.json
1041 share/datetime/en_ca.json
1042 share/functions/en_ca.js
1043 share/misc_info/en_gb.js
1044 share/code_to_name/en_gb.json
1045 share/datetime/en_gb.json
1046 share/functions/en_gb.js
1047 share/misc_info/en_us.js
1048 share/code_to_name/en_us.json
1049 share/datetime/en_us.json
1050 share/functions/en_us.js
1051 share/misc_info/eo.js
1052 share/code_to_name/eo.json
1053 share/datetime/eo.json
1054 share/functions/eo.js
1055 share/misc_info/es.js
1056 share/code_to_name/es.json
1057 share/datetime/es.json
1058 share/functions/es.js
1059 share/misc_info/es_419.js
1060 share/code_to_name/es_419.json
1061 share/datetime/es_419.json
1062 share/functions/es_419.js
1063 share/misc_info/es_es.js
1064 share/code_to_name/es_es.json
1065 share/datetime/es_es.json
1066 share/functions/es_es.js
1067 share/misc_info/et.js
1068 share/code_to_name/et.json
1069 share/datetime/et.json
1070 share/functions/et.js
1071 share/misc_info/eu.js
1072 share/code_to_name/eu.json
1073 share/datetime/eu.json
1074 share/functions/eu.js
1075 share/misc_info/ewo.js
1076 share/code_to_name/ewo.json
1077 share/datetime/ewo.json
1078 share/functions/ewo.js
1079 share/misc_info/fa.js
1080 share/code_to_name/fa.json
1081 share/datetime/fa.json
1082 share/functions/fa.js
1083 share/misc_info/ff.js
1084 share/code_to_name/ff.json
1085 share/datetime/ff.json
1086 share/functions/ff.js
1087 share/misc_info/fi.js
1088 share/code_to_name/fi.json
1089 share/datetime/fi.json
1090 share/functions/fi.js
1091 share/misc_info/fil.js
1092 share/code_to_name/fil.json
1093 share/datetime/fil.json
1094 share/functions/fil.js
1095 share/misc_info/fo.js
1096 share/code_to_name/fo.json
1097 share/datetime/fo.json
1098 share/functions/fo.js
1099 share/misc_info/fr.js
1100 share/code_to_name/fr.json
1101 share/datetime/fr.json
1102 share/functions/fr.js
1103 share/misc_info/fr_ca.js
1104 share/code_to_name/fr_ca.json
1105 share/datetime/fr_ca.json
1106 share/functions/fr_ca.js
1107 share/misc_info/fr_ch.js
1108 share/code_to_name/fr_ch.json
1109 share/datetime/fr_ch.json
1110 share/functions/fr_ch.js
1111 share/misc_info/fur.js
1112 share/code_to_name/fur.json
1113 share/datetime/fur.json
1114 share/functions/fur.js
1115 share/misc_info/ga.js
1116 share/code_to_name/ga.json
1117 share/datetime/ga.json
1118 share/functions/ga.js
1119 share/misc_info/gaa.js
1120 share/code_to_name/gaa.json
1121 share/datetime/gaa.json
1122 share/functions/gaa.js
1123 share/misc_info/gl.js
1124 share/code_to_name/gl.json
1125 share/datetime/gl.json
1126 share/functions/gl.js
1127 share/misc_info/gsw.js
1128 share/code_to_name/gsw.json
1129 share/datetime/gsw.json
1130 share/functions/gsw.js
1131 share/misc_info/gu.js
1132 share/code_to_name/gu.json
1133 share/datetime/gu.json
1134 share/functions/gu.js
1135 share/misc_info/guz.js
1136 share/code_to_name/guz.json
1137 share/datetime/guz.json
1138 share/functions/guz.js
1139 share/misc_info/gv.js
1140 share/code_to_name/gv.json
1141 share/datetime/gv.json
1142 share/functions/gv.js
1143 share/misc_info/ha.js
1144 share/code_to_name/ha.json
1145 share/datetime/ha.json
1146 share/functions/ha.js
1147 share/misc_info/haw.js
1148 share/code_to_name/haw.json
1149 share/datetime/haw.json
1150 share/functions/haw.js
1151 share/misc_info/he.js
1152 share/code_to_name/he.json
1153 share/datetime/he.json
1154 share/functions/he.js
1155 share/misc_info/hi.js
1156 share/code_to_name/hi.json
1157 share/datetime/hi.json
1158 share/functions/hi.js
1159 share/misc_info/hr.js
1160 share/code_to_name/hr.json
1161 share/datetime/hr.json
1162 share/functions/hr.js
1163 share/misc_info/hu.js
1164 share/code_to_name/hu.json
1165 share/datetime/hu.json
1166 share/functions/hu.js
1167 share/misc_info/hy.js
1168 share/code_to_name/hy.json
1169 share/datetime/hy.json
1170 share/functions/hy.js
1171 share/misc_info/ia.js
1172 share/code_to_name/ia.json
1173 share/datetime/ia.json
1174 share/functions/ia.js
1175 share/misc_info/id.js
1176 share/code_to_name/id.json
1177 share/datetime/id.json
1178 share/functions/id.js
1179 share/misc_info/ig.js
1180 share/code_to_name/ig.json
1181 share/datetime/ig.json
1182 share/functions/ig.js
1183 share/misc_info/ii.js
1184 share/code_to_name/ii.json
1185 share/datetime/ii.json
1186 share/functions/ii.js
1187 share/misc_info/is.js
1188 share/code_to_name/is.json
1189 share/datetime/is.json
1190 share/functions/is.js
1191 share/misc_info/it.js
1192 share/code_to_name/it.json
1193 share/datetime/it.json
1194 share/functions/it.js
1195 share/misc_info/ja.js
1196 share/code_to_name/ja.json
1197 share/datetime/ja.json
1198 share/functions/ja.js
1199 share/misc_info/jmc.js
1200 share/code_to_name/jmc.json
1201 share/datetime/jmc.json
1202 share/functions/jmc.js
1203 share/misc_info/ka.js
1204 share/code_to_name/ka.json
1205 share/datetime/ka.json
1206 share/functions/ka.js
1207 share/misc_info/kab.js
1208 share/code_to_name/kab.json
1209 share/datetime/kab.json
1210 share/functions/kab.js
1211 share/misc_info/kaj.js
1212 share/code_to_name/kaj.json
1213 share/datetime/kaj.json
1214 share/functions/kaj.js
1215 share/misc_info/kam.js
1216 share/code_to_name/kam.json
1217 share/datetime/kam.json
1218 share/functions/kam.js
1219 share/misc_info/kcg.js
1220 share/code_to_name/kcg.json
1221 share/datetime/kcg.json
1222 share/functions/kcg.js
1223 share/misc_info/kde.js
1224 share/code_to_name/kde.json
1225 share/datetime/kde.json
1226 share/functions/kde.js
1227 share/misc_info/kea.js
1228 share/code_to_name/kea.json
1229 share/datetime/kea.json
1230 share/functions/kea.js
1231 share/misc_info/khq.js
1232 share/code_to_name/khq.json
1233 share/datetime/khq.json
1234 share/functions/khq.js
1235 share/misc_info/ki.js
1236 share/code_to_name/ki.json
1237 share/datetime/ki.json
1238 share/functions/ki.js
1239 share/misc_info/kk.js
1240 share/code_to_name/kk.json
1241 share/datetime/kk.json
1242 share/functions/kk.js
1243 share/misc_info/kl.js
1244 share/code_to_name/kl.json
1245 share/datetime/kl.json
1246 share/functions/kl.js
1247 share/misc_info/kln.js
1248 share/code_to_name/kln.json
1249 share/datetime/kln.json
1250 share/functions/kln.js
1251 share/misc_info/km.js
1252 share/code_to_name/km.json
1253 share/datetime/km.json
1254 share/functions/km.js
1255 share/misc_info/kn.js
1256 share/code_to_name/kn.json
1257 share/datetime/kn.json
1258 share/functions/kn.js
1259 share/misc_info/ko.js
1260 share/code_to_name/ko.json
1261 share/datetime/ko.json
1262 share/functions/ko.js
1263 share/misc_info/kok.js
1264 share/code_to_name/kok.json
1265 share/datetime/kok.json
1266 share/functions/kok.js
1267 share/misc_info/ksb.js
1268 share/code_to_name/ksb.json
1269 share/datetime/ksb.json
1270 share/functions/ksb.js
1271 share/misc_info/ksf.js
1272 share/code_to_name/ksf.json
1273 share/datetime/ksf.json
1274 share/functions/ksf.js
1275 share/misc_info/ksh.js
1276 share/code_to_name/ksh.json
1277 share/datetime/ksh.json
1278 share/functions/ksh.js
1279 share/misc_info/ku.js
1280 share/code_to_name/ku.json
1281 share/datetime/ku.json
1282 share/functions/ku.js
1283 share/misc_info/kw.js
1284 share/code_to_name/kw.json
1285 share/datetime/kw.json
1286 share/functions/kw.js
1287 share/misc_info/ky.js
1288 share/code_to_name/ky.json
1289 share/datetime/ky.json
1290 share/functions/ky.js
1291 share/misc_info/lag.js
1292 share/code_to_name/lag.json
1293 share/datetime/lag.json
1294 share/functions/lag.js
1295 share/misc_info/lg.js
1296 share/code_to_name/lg.json
1297 share/datetime/lg.json
1298 share/functions/lg.js
1299 share/misc_info/ln.js
1300 share/code_to_name/ln.json
1301 share/datetime/ln.json
1302 share/functions/ln.js
1303 share/misc_info/lo.js
1304 share/code_to_name/lo.json
1305 share/datetime/lo.json
1306 share/functions/lo.js
1307 share/misc_info/lt.js
1308 share/code_to_name/lt.json
1309 share/datetime/lt.json
1310 share/functions/lt.js
1311 share/misc_info/lu.js
1312 share/code_to_name/lu.json
1313 share/datetime/lu.json
1314 share/functions/lu.js
1315 share/misc_info/luo.js
1316 share/code_to_name/luo.json
1317 share/datetime/luo.json
1318 share/functions/luo.js
1319 share/misc_info/luy.js
1320 share/code_to_name/luy.json
1321 share/datetime/luy.json
1322 share/functions/luy.js
1323 share/misc_info/lv.js
1324 share/code_to_name/lv.json
1325 share/datetime/lv.json
1326 share/functions/lv.js
1327 share/misc_info/mas.js
1328 share/code_to_name/mas.json
1329 share/datetime/mas.json
1330 share/functions/mas.js
1331 share/misc_info/mer.js
1332 share/code_to_name/mer.json
1333 share/datetime/mer.json
1334 share/functions/mer.js
1335 share/misc_info/mfe.js
1336 share/code_to_name/mfe.json
1337 share/datetime/mfe.json
1338 share/functions/mfe.js
1339 share/misc_info/mg.js
1340 share/code_to_name/mg.json
1341 share/datetime/mg.json
1342 share/functions/mg.js
1343 share/misc_info/mgh.js
1344 share/code_to_name/mgh.json
1345 share/datetime/mgh.json
1346 share/functions/mgh.js
1347 share/misc_info/mk.js
1348 share/code_to_name/mk.json
1349 share/datetime/mk.json
1350 share/functions/mk.js
1351 share/misc_info/ml.js
1352 share/code_to_name/ml.json
1353 share/datetime/ml.json
1354 share/functions/ml.js
1355 share/misc_info/mn.js
1356 share/code_to_name/mn.json
1357 share/datetime/mn.json
1358 share/functions/mn.js
1359 share/misc_info/mo.js
1360 share/code_to_name/mo.json
1361 share/datetime/mo.json
1362 share/functions/mo.js
1363 share/misc_info/mr.js
1364 share/code_to_name/mr.json
1365 share/datetime/mr.json
1366 share/functions/mr.js
1367 share/misc_info/ms.js
1368 share/code_to_name/ms.json
1369 share/datetime/ms.json
1370 share/functions/ms.js
1371 share/misc_info/mt.js
1372 share/code_to_name/mt.json
1373 share/datetime/mt.json
1374 share/functions/mt.js
1375 share/misc_info/mua.js
1376 share/code_to_name/mua.json
1377 share/datetime/mua.json
1378 share/functions/mua.js
1379 share/misc_info/my.js
1380 share/code_to_name/my.json
1381 share/datetime/my.json
1382 share/functions/my.js
1383 share/misc_info/naq.js
1384 share/code_to_name/naq.json
1385 share/datetime/naq.json
1386 share/functions/naq.js
1387 share/misc_info/nb.js
1388 share/code_to_name/nb.json
1389 share/datetime/nb.json
1390 share/functions/nb.js
1391 share/misc_info/nd.js
1392 share/code_to_name/nd.json
1393 share/datetime/nd.json
1394 share/functions/nd.js
1395 share/misc_info/nds.js
1396 share/code_to_name/nds.json
1397 share/datetime/nds.json
1398 share/functions/nds.js
1399 share/misc_info/ne.js
1400 share/code_to_name/ne.json
1401 share/datetime/ne.json
1402 share/functions/ne.js
1403 share/misc_info/nl.js
1404 share/code_to_name/nl.json
1405 share/datetime/nl.json
1406 share/functions/nl.js
1407 share/misc_info/nl_be.js
1408 share/code_to_name/nl_be.json
1409 share/datetime/nl_be.json
1410 share/functions/nl_be.js
1411 share/misc_info/nmg.js
1412 share/code_to_name/nmg.json
1413 share/datetime/nmg.json
1414 share/functions/nmg.js
1415 share/misc_info/nn.js
1416 share/code_to_name/nn.json
1417 share/datetime/nn.json
1418 share/functions/nn.js
1419 share/misc_info/no.js
1420 share/code_to_name/no.json
1421 share/datetime/no.json
1422 share/functions/no.js
1423 share/misc_info/nr.js
1424 share/code_to_name/nr.json
1425 share/datetime/nr.json
1426 share/functions/nr.js
1427 share/misc_info/nso.js
1428 share/code_to_name/nso.json
1429 share/datetime/nso.json
1430 share/functions/nso.js
1431 share/misc_info/nus.js
1432 share/code_to_name/nus.json
1433 share/datetime/nus.json
1434 share/functions/nus.js
1435 share/misc_info/nyn.js
1436 share/code_to_name/nyn.json
1437 share/datetime/nyn.json
1438 share/functions/nyn.js
1439 share/misc_info/oc.js
1440 share/code_to_name/oc.json
1441 share/datetime/oc.json
1442 share/functions/oc.js
1443 share/misc_info/om.js
1444 share/code_to_name/om.json
1445 share/datetime/om.json
1446 share/functions/om.js
1447 share/misc_info/or.js
1448 share/code_to_name/or.json
1449 share/datetime/or.json
1450 share/functions/or.js
1451 share/misc_info/pa.js
1452 share/code_to_name/pa.json
1453 share/datetime/pa.json
1454 share/functions/pa.js
1455 share/misc_info/pl.js
1456 share/code_to_name/pl.json
1457 share/datetime/pl.json
1458 share/functions/pl.js
1459 share/misc_info/ps.js
1460 share/code_to_name/ps.json
1461 share/datetime/ps.json
1462 share/functions/ps.js
1463 share/misc_info/pt.js
1464 share/code_to_name/pt.json
1465 share/datetime/pt.json
1466 share/functions/pt.js
1467 share/misc_info/pt_br.js
1468 share/code_to_name/pt_br.json
1469 share/datetime/pt_br.json
1470 share/functions/pt_br.js
1471 share/misc_info/pt_pt.js
1472 share/code_to_name/pt_pt.json
1473 share/datetime/pt_pt.json
1474 share/functions/pt_pt.js
1475 share/misc_info/rm.js
1476 share/code_to_name/rm.json
1477 share/datetime/rm.json
1478 share/functions/rm.js
1479 share/misc_info/rn.js
1480 share/code_to_name/rn.json
1481 share/datetime/rn.json
1482 share/functions/rn.js
1483 share/misc_info/ro.js
1484 share/code_to_name/ro.json
1485 share/datetime/ro.json
1486 share/functions/ro.js
1487 share/misc_info/rof.js
1488 share/code_to_name/rof.json
1489 share/datetime/rof.json
1490 share/functions/rof.js
1491 share/misc_info/ru.js
1492 share/code_to_name/ru.json
1493 share/datetime/ru.json
1494 share/functions/ru.js
1495 share/misc_info/rw.js
1496 share/code_to_name/rw.json
1497 share/datetime/rw.json
1498 share/functions/rw.js
1499 share/misc_info/rwk.js
1500 share/code_to_name/rwk.json
1501 share/datetime/rwk.json
1502 share/functions/rwk.js
1503 share/misc_info/sah.js
1504 share/code_to_name/sah.json
1505 share/datetime/sah.json
1506 share/functions/sah.js
1507 share/misc_info/saq.js
1508 share/code_to_name/saq.json
1509 share/datetime/saq.json
1510 share/functions/saq.js
1511 share/misc_info/sbp.js
1512 share/code_to_name/sbp.json
1513 share/datetime/sbp.json
1514 share/functions/sbp.js
1515 share/misc_info/se.js
1516 share/code_to_name/se.json
1517 share/datetime/se.json
1518 share/functions/se.js
1519 share/misc_info/seh.js
1520 share/code_to_name/seh.json
1521 share/datetime/seh.json
1522 share/functions/seh.js
1523 share/misc_info/ses.js
1524 share/code_to_name/ses.json
1525 share/datetime/ses.json
1526 share/functions/ses.js
1527 share/misc_info/sg.js
1528 share/code_to_name/sg.json
1529 share/datetime/sg.json
1530 share/functions/sg.js
1531 share/misc_info/sh.js
1532 share/code_to_name/sh.json
1533 share/datetime/sh.json
1534 share/functions/sh.js
1535 share/misc_info/shi.js
1536 share/code_to_name/shi.json
1537 share/datetime/shi.json
1538 share/functions/shi.js
1539 share/misc_info/si.js
1540 share/code_to_name/si.json
1541 share/datetime/si.json
1542 share/functions/si.js
1543 share/misc_info/sid.js
1544 share/code_to_name/sid.json
1545 share/datetime/sid.json
1546 share/functions/sid.js
1547 share/misc_info/sk.js
1548 share/code_to_name/sk.json
1549 share/datetime/sk.json
1550 share/functions/sk.js
1551 share/misc_info/sl.js
1552 share/code_to_name/sl.json
1553 share/datetime/sl.json
1554 share/functions/sl.js
1555 share/misc_info/sn.js
1556 share/code_to_name/sn.json
1557 share/datetime/sn.json
1558 share/functions/sn.js
1559 share/misc_info/so.js
1560 share/code_to_name/so.json
1561 share/datetime/so.json
1562 share/functions/so.js
1563 share/misc_info/sq.js
1564 share/code_to_name/sq.json
1565 share/datetime/sq.json
1566 share/functions/sq.js
1567 share/misc_info/sr.js
1568 share/code_to_name/sr.json
1569 share/datetime/sr.json
1570 share/functions/sr.js
1571 share/misc_info/ss.js
1572 share/code_to_name/ss.json
1573 share/datetime/ss.json
1574 share/functions/ss.js
1575 share/misc_info/ssy.js
1576 share/code_to_name/ssy.json
1577 share/datetime/ssy.json
1578 share/functions/ssy.js
1579 share/misc_info/st.js
1580 share/code_to_name/st.json
1581 share/datetime/st.json
1582 share/functions/st.js
1583 share/misc_info/sv.js
1584 share/code_to_name/sv.json
1585 share/datetime/sv.json
1586 share/functions/sv.js
1587 share/misc_info/sw.js
1588 share/code_to_name/sw.json
1589 share/datetime/sw.json
1590 share/functions/sw.js
1591 share/misc_info/swc.js
1592 share/code_to_name/swc.json
1593 share/datetime/swc.json
1594 share/functions/swc.js
1595 share/misc_info/ta.js
1596 share/code_to_name/ta.json
1597 share/datetime/ta.json
1598 share/functions/ta.js
1599 share/misc_info/te.js
1600 share/code_to_name/te.json
1601 share/datetime/te.json
1602 share/functions/te.js
1603 share/misc_info/teo.js
1604 share/code_to_name/teo.json
1605 share/datetime/teo.json
1606 share/functions/teo.js
1607 share/misc_info/tg.js
1608 share/code_to_name/tg.json
1609 share/datetime/tg.json
1610 share/functions/tg.js
1611 share/misc_info/th.js
1612 share/code_to_name/th.json
1613 share/datetime/th.json
1614 share/functions/th.js
1615 share/misc_info/ti.js
1616 share/code_to_name/ti.json
1617 share/datetime/ti.json
1618 share/functions/ti.js
1619 share/misc_info/tig.js
1620 share/code_to_name/tig.json
1621 share/datetime/tig.json
1622 share/functions/tig.js
1623 share/misc_info/tl.js
1624 share/code_to_name/tl.json
1625 share/datetime/tl.json
1626 share/functions/tl.js
1627 share/misc_info/tn.js
1628 share/code_to_name/tn.json
1629 share/datetime/tn.json
1630 share/functions/tn.js
1631 share/misc_info/to.js
1632 share/code_to_name/to.json
1633 share/datetime/to.json
1634 share/functions/to.js
1635 share/misc_info/tr.js
1636 share/code_to_name/tr.json
1637 share/datetime/tr.json
1638 share/functions/tr.js
1639 share/misc_info/trv.js
1640 share/code_to_name/trv.json
1641 share/datetime/trv.json
1642 share/functions/trv.js
1643 share/misc_info/ts.js
1644 share/code_to_name/ts.json
1645 share/datetime/ts.json
1646 share/functions/ts.js
1647 share/misc_info/twq.js
1648 share/code_to_name/twq.json
1649 share/datetime/twq.json
1650 share/functions/twq.js
1651 share/misc_info/tzm.js
1652 share/code_to_name/tzm.json
1653 share/datetime/tzm.json
1654 share/functions/tzm.js
1655 share/misc_info/uk.js
1656 share/code_to_name/uk.json
1657 share/datetime/uk.json
1658 share/functions/uk.js
1659 share/misc_info/ur.js
1660 share/code_to_name/ur.json
1661 share/datetime/ur.json
1662 share/functions/ur.js
1663 share/misc_info/uz.js
1664 share/code_to_name/uz.json
1665 share/datetime/uz.json
1666 share/functions/uz.js
1667 share/misc_info/vai.js
1668 share/code_to_name/vai.json
1669 share/datetime/vai.json
1670 share/functions/vai.js
1671 share/misc_info/ve.js
1672 share/code_to_name/ve.json
1673 share/datetime/ve.json
1674 share/functions/ve.js
1675 share/misc_info/vi.js
1676 share/code_to_name/vi.json
1677 share/datetime/vi.json
1678 share/functions/vi.js
1679 share/misc_info/vun.js
1680 share/code_to_name/vun.json
1681 share/datetime/vun.json
1682 share/functions/vun.js
1683 share/misc_info/wae.js
1684 share/code_to_name/wae.json
1685 share/datetime/wae.json
1686 share/functions/wae.js
1687 share/misc_info/wal.js
1688 share/code_to_name/wal.json
1689 share/datetime/wal.json
1690 share/functions/wal.js
1691 share/misc_info/xh.js
1692 share/code_to_name/xh.json
1693 share/datetime/xh.json
1694 share/functions/xh.js
1695 share/misc_info/xog.js
1696 share/code_to_name/xog.json
1697 share/datetime/xog.json
1698 share/functions/xog.js
1699 share/misc_info/yav.js
1700 share/code_to_name/yav.json
1701 share/datetime/yav.json
1702 share/functions/yav.js
1703 share/misc_info/yo.js
1704 share/code_to_name/yo.json
1705 share/datetime/yo.json
1706 share/functions/yo.js
1707 share/misc_info/zh.js
1708 share/code_to_name/zh.json
1709 share/datetime/zh.json
1710 share/functions/zh.js
1711 share/misc_info/zu.js
1712 share/code_to_name/zu.json
1713 share/datetime/zu.json
1714 share/functions/zu.js
1715 share/db/loadable.json
8701716 META.yml Module YAML meta-data (added by MakeMaker)
8711717 META.json Module JSON meta-data (added by MakeMaker)
22 "author" : [
33 "Daniel Muey <http://drmuey.com/cpan_contact.pl>"
44 ],
5 "dynamic_config" : 1,
6 "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.150001",
5 "dynamic_config" : 0,
6 "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010",
77 "license" : [
88 "unknown"
99 ],
1010 "meta-spec" : {
1111 "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
12 "version" : "2"
12 "version" : 2
1313 },
1414 "name" : "Locales",
1515 "no_index" : {
4444 }
4545 },
4646 "release_status" : "stable",
47 "version" : "0.34"
47 "resources" : {
48 "bugtracker" : {
49 "web" : "https://github.com/drmuey/p5-Locales/issues"
50 },
51 "repository" : {
52 "type" : "git",
53 "url" : "https://github.com/drmuey/p5-Locales.git",
54 "web" : "https://github.com/drmuey/p5-Locales"
55 }
56 },
57 "version" : "0.34",
58 "x_serialization_backend" : "JSON::PP version 4.07"
4859 }
88 Test::More: '0'
99 configure_requires:
1010 ExtUtils::MakeMaker: '6.56'
11 dynamic_config: 1
12 generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.150001'
11 dynamic_config: 0
12 generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010'
1313 license: unknown
1414 meta-spec:
1515 url: http://module-build.sourceforge.net/META-spec-v1.4.html
2626 String::UnicodeUTF8: '0'
2727 Test::Carp: '0'
2828 Test::More: '0'
29 resources:
30 bugtracker: https://github.com/drmuey/p5-Locales/issues
31 repository: https://github.com/drmuey/p5-Locales.git
2932 version: '0.34'
33 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
2424 CONFIGURE_REQUIRES => {
2525 'ExtUtils::MakeMaker' => 6.56,
2626 },
27 dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
28 clean => { FILES => 'Locales-*' },
27 dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
28 clean => { FILES => 'Locales-*' },
29 META_ADD => {
30 'meta-spec' => { version => 2 },
31 dynamic_config => 0,
32 resources => {
33 repository => {
34 url => 'https://github.com/drmuey/p5-Locales.git',
35 web => 'https://github.com/drmuey/p5-Locales',
36 type => 'git',
37 },
38 bugtracker => {
39 web => 'https://github.com/drmuey/p5-Locales/issues',
40 },
41 },
42 },
2943 );
0 How to update:
1
2 0) get latest CLDR from http://cldr.unicode.org/index/downloads
3
4 1) update $Locales::CLDR_VERSION && $Locales::VERSION
5
6 2) build modules out of CLDR, something like this:
7
8 Note: If the DB mods are NOT changing you'll have to update "my $v_offset" in _locales_build_utils.pm && perl -pi -e 's{0\.25}{0.26}g;' t/042.*
9
10 ./_build/cldr2locales ../Downloads/
11
12 ../Downloads/ == path to downloaded and extracted CLDR core (should contain 'common/main' dir)
13
14 3) do any other changes
15
16 4) tidy it all (rt 69971)
17
18 perltidy -b `find lib/Locales/DB -name '*.pm'`
19 perltidy -b lib/Locales.pm
20 rm `find . -name '*.bak'`
21
22 5) perl Makefile.PL && make && make test
23
24 6) RELEASE_TESTING=1 make test
25
26 7) ... make dist && sudo make install
0 package _locales_build_utils;
1
2 use Cwd;
3 use XML::Simple;
4 use XML::Twig;
5 use File::Path::Tiny;
6 use lib Cwd::realpath('lib');
7 use Locales;
8 use File::Slurp;
9 use Encode (); # to be stringified properly from hash value bug: s{\|\|\s*(\$fallback_lang_misc_info\-\>\S*)\,}{|| Encode::decode_utf8($1),}
10 use String::Unquotemeta;
11 use JSON::Syck;
12 use JavaScript::Minifier::XS;
13
14 #### this ugliness will be spruced up when we go to CLDR-via-JSON in rt 69340 (no XML voo doo and we can move to TT for mod building) ##
15
16 # datetime.json
17 our $tripped;
18 use Test::Carp sub { $tripped = 1 if $_[0]; };
19 use DateTime::Locale;
20 use Class::Inspector;
21 my $en_dt_loc = DateTime::Locale->load('en');
22 my @dt_methods;
23 for my $meth ( @{ Class::Inspector->methods( ref($en_dt_loc), "public" ) } ) {
24 next if $meth eq 'new' || $meth eq 'carp' || $meth eq 'format_for' || $meth eq 'validate_pos';
25 next if $meth =~ m/^(:?set_|STORABLE_)/;
26
27 *DateTime::Locale::Base::carp = sub { Carp::carp( $_[0] ) };
28 local $tripped = 0;
29 Test::Carp::does_carp_that_matches(
30 sub {
31 eval { $en_dt_loc->$meth() };
32 },
33 qr/The $meth method in DateTime::Locale::Base has been deprecated/
34 );
35 next if $tripped;
36
37 push @dt_methods, $meth;
38 }
39 my @dt_available_formats = $en_dt_loc->available_formats();
40
41 # /datetime.json
42
43 use Hash::Merge;
44 Hash::Merge::specify_behavior(
45 {
46 'SCALAR' => {
47 'SCALAR' => sub { !defined $_[0] ? $_[1] : $_[0] },
48 'ARRAY' => sub { !defined $_[0] ? $_[1] : $_[0] },
49 'HASH' => sub { !defined $_[0] ? $_[1] : $_[0] },
50 },
51 'ARRAY' => {
52 'SCALAR' => sub { defined $_[0] ? $_[0] : [ @{ $_[0] }, $_[1] ] },
53 'ARRAY' => sub { defined $_[0] ? $_[0] : [ @{ $_[0] }, @{ $_[1] } ] },
54 'HASH' => sub { defined $_[0] ? $_[0] : [ @{ $_[0] }, values %{ $_[1] } ] },
55 },
56 'HASH' => {
57 'SCALAR' => sub { $_[0] },
58 'ARRAY' => sub { $_[0] },
59 'HASH' => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) },
60 },
61 },
62 "left undef/missing"
63 );
64
65 sub merge_hash {
66 goto &Hash::Merge::merge;
67 }
68 use Data::Dumper;
69 $Data::Dumper::Terse = 1;
70 $Data::Dumper::Sortkeys = 1;
71 $Data::Dumper::Useqq = 1;
72 {
73 no warnings 'redefine';
74
75 sub Data::Dumper::qquote {
76 my $s = shift;
77 my $q = quotemeta($s);
78 return $s ne $q ? qq{"$q"} : qq{'$s'};
79 }
80 }
81
82 my $v_offset = '0.24';
83 my $mod_version = $Locales::VERSION - $v_offset;
84 my $cldr_version = $Locales::cldr_version;
85 my $cldr_db_path;
86 my $locales_db;
87 my $manifest;
88 our $plural_forms;
89
90 sub init_paths_from_argv {
91 die "no CLDR path given" if !-d "$ARGV[0]/common/main";
92 $cldr_db_path = Cwd::realpath( $ARGV[0] ) || die "need path to CLDR";
93 $locales_db = Cwd::realpath( $SARGV[1] || 'lib/Locales/DB' );
94 $manifest = Cwd::realpath( $SARGV[2] || 'MANIFEST.build' );
95
96 my $plural_forms_xml = XMLin( "$ARGV[0]/common/supplemental/plurals.xml", ForceArray => 1 ); # ,'KeyAttr' => {'pluralRules' => '+locales' });
97 for my $plural ( @{ $plural_forms_xml->{'plurals'}[0]{'pluralRules'} } ) {
98 for my $loc ( split( /\s+/, $plural->{'locales'} ) ) {
99 $plural_forms->{$loc} = { map { $_->{'count'} => $_->{'content'} } @{ $plural->{'pluralRule'} } };
100 if ( !keys %{ $plural_forms->{$loc} } ) {
101 $plural_forms->{$loc} = undef();
102 }
103 }
104 }
105
106 # print Dumper($plural_forms);die; # _xml->{'plurals'}[0]{'pluralRules'});die;
107
108 return ( $cldr_db_path, $locales_db, $manifest );
109 }
110
111 sub get_xml_file_for {
112 my ( $tag, $quiet ) = @_;
113 my $xml_file = "$cldr_db_path/common/main/$tag.xml";
114 if ( !-e $xml_file ) {
115 warn "\t1) No $xml_file ...\n" if !$quiet;
116 my $tag_copy = $tag;
117 $tag_copy =~ s{_(\w+)$}{_\U$1\E};
118 $xml_file = "$cldr_db_path/common/main/$tag_copy.xml";
119 if ( !-e $xml_file ) {
120 warn "\t2) No $xml_file ...\n" if !$quiet;
121 $tag_copy =~ tr/a-z/A-Z/;
122 $xml_file = "$cldr_db_path/common/main/$tag_copy.xml";
123 if ( !-e $xml_file ) {
124 warn "\t3) No $xml_file ...\n" if !$quiet;
125 return;
126 }
127 }
128 }
129 return $xml_file;
130
131 }
132
133 sub get_target_structs_from_cldr_for_tag {
134 my ( $tag, $fallback_lang_code_to_name, $fallback_terr_code_to_name, $fallback_lang_misc_info ) = @_;
135
136 # if ( $tag eq 'pt_br' ) { print Dumper( [ 'get_target_structs_from_cldr_for_tag', $fallback_lang_misc_info ] ) }
137 my $xml_file = get_xml_file_for($tag);
138 return if !-e $xml_file;
139
140 print "Loading $tag XML from $xml_file...\n";
141
142 # my $raw_struct = XMLin($xml_file, 'KeyAttr' => 'type');
143 my $raw_struct = XML::Twig->new()->parsefile($xml_file)->simplify(
144 'keyattr' => {
145 'codePattern' => '+type',
146 'listPatternPart' => '+type',
147 'characters' => '+type',
148 'ellipsis' => '+type',
149 'territory' => '+type',
150 'language' => '+type',
151 }
152 );
153
154 my ( $lang_code_to_name, $lang_name_to_code, $lang_misc_info, $terr_code_to_name, $terr_name_to_code ) = ( {}, {}, {}, {}, {} );
155
156 #### Territories ####
157 for my $trr ( keys %{ $raw_struct->{'localeDisplayNames'}{'territories'}{'territory'} } ) {
158
159 # Do not skip ISO 3166-1-numeric (e.g. 419, as in es_419)
160 # next if $trr =~ m/^\d+$/;
161
162 my $short = $trr;
163 $short =~ tr/A-Z/a-z/;
164
165 $terr_code_to_name->{$short} = $raw_struct->{'localeDisplayNames'}{'territories'}{'territory'}{$trr}{'content'};
166 $terr_name_to_code->{ Locales::normalize_for_key_lookup( $raw_struct->{'localeDisplayNames'}{'territories'}{'territory'}{$trr}{'content'} ) } = $short;
167 }
168
169 if ($fallback_terr_code_to_name) {
170 for my $fb_trr ( keys %{$fallback_terr_code_to_name} ) {
171 if ( !exists $terr_code_to_name->{$fb_trr} ) {
172 $terr_code_to_name->{$fb_trr} = $fallback_terr_code_to_name->{$fb_trr};
173 $terr_name_to_code->{ Locales::normalize_for_key_lookup( $fallback_terr_code_to_name->{$fb_trr} ) } = $fb_trr;
174 }
175 }
176 }
177 #### /Territories ####
178
179 #### Languages ####
180 my $fallback = undef; # or [] ?
181 if ( exists $raw_struct->{'fallback'} ) {
182 $fallback = [];
183 if ( my $type = ref( $raw_struct->{'fallback'} ) ) {
184 if ( $type eq 'ARRAY' ) {
185 for my $fb ( @{ $raw_struct->{'fallback'} } ) {
186 my $thing = ref($fb) ? $fb->{'content'} : $fb;
187 next if !defined $thing;
188 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $thing );
189 }
190 }
191 elsif ( $type eq 'HASH' ) {
192 if ( $raw_struct->{'fallback'}{'content'} ) {
193 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $raw_struct->{'fallback'}{'content'} );
194 }
195 }
196 }
197 else {
198 if ( $raw_struct->{'fallback'} ) {
199 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $raw_struct->{'fallback'} );
200 }
201 }
202 }
203 elsif ( exists $fallback_lang_misc_info->{'fallback'} ) {
204 $fallback = [];
205 if ( my $type = ref( $fallback_lang_misc_info->{'fallback'} ) ) {
206 if ( $type eq 'ARRAY' ) {
207 for my $fb ( @{ $fallback_lang_misc_info->{'fallback'} } ) {
208 my $thing = ref($fb) ? $fb->{'content'} : $fb;
209 next if !defined $thing;
210 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $thing );
211 }
212 }
213 elsif ( $type eq 'HASH' ) {
214 if ( $fallback_lang_misc_info->{'fallback'}{'content'} ) {
215 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $fallback_lang_misc_info->{'fallback'}{'content'} );
216 }
217 }
218 }
219 else {
220 if ( $fallback_lang_misc_info->{'fallback'} ) {
221 push @{$fallback}, map { Locales::normalize_tag("$_") } split( /\s+/, $fallback_lang_misc_info->{'fallback'} );
222 }
223 }
224 }
225
226 my $symbols_index;
227 if ( ref( $raw_struct->{'numbers'}{'symbols'} ) eq 'ARRAY' ) {
228 my $default_numbersystem = $raw_struct->{'numbers'}{'defaultNumberingSystem'} || $raw_struct->{'numbers'}{'defaultNumberingSystem'} || 'latn';
229 if ( ref($default_numbersystem) eq 'HASH' ) {
230 $default_numbersystem = $default_numbersystem->{'content'};
231 }
232
233 my $idx = -1;
234 for my $item ( @{ $raw_struct->{'numbers'}{'symbols'} } ) {
235 $idx++;
236
237 if ( ref($item) eq 'HASH' && $item->{'numberSystem'} eq $default_numbersystem ) {
238 $symbols_index = $idx;
239 last;
240 }
241 }
242 }
243
244 my $_decimal_format_group =
245 defined $symbols_index
246 ? (
247 ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'group'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'group'}{'content'}
248 : ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'group'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'group'}->[0]
249 : $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'group'}
250 )
251 : (
252 ref $raw_struct->{'numbers'}{'symbols'}{'group'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}{'group'}{'content'}
253 : ref $raw_struct->{'numbers'}{'symbols'}{'group'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}{'group'}->[0]
254 : $raw_struct->{'numbers'}{'symbols'}{'group'}
255 );
256 if ( ref($_decimal_format_group) eq 'HASH' ) {
257 $_decimal_format_group = $_decimal_format_group->{'content'};
258 }
259
260 my $_decimal_format_decimal = defined $symbols_index
261 ? (
262 ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'decimal'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'decimal'}{'content'}
263 : ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'decimal'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'decimal'}->[0]
264 : $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'decimal'}
265
266 )
267 : (
268 ref $raw_struct->{'numbers'}{'symbols'}{'decimal'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}{'decimal'}{'content'}
269 : ref $raw_struct->{'numbers'}{'symbols'}{'decimal'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}{'decimal'}->[0]
270 : $raw_struct->{'numbers'}{'symbols'}{'decimal'}
271 );
272 if ( ref($_decimal_format_decimal) eq 'HASH' ) {
273 $_decimal_format_decimal = $_decimal_format_decimal->{'content'};
274 }
275
276 # only fallback if *both* will match
277 if ( !$_decimal_format_group && !$_decimal_format_decimal ) {
278 $_decimal_format_group = $fallback_lang_misc_info->{'cldr_formats'}{'_decimal_format_group'};
279 $_decimal_format_decimal = $fallback_lang_misc_info->{'cldr_formats'}{'_decimal_format_decimal'};
280 }
281
282 # if we are missing one use both it's parent's data if possible
283 if ( !$_decimal_format_group || !$_decimal_format_decimal ) {
284 my ( $l, $t ) = Locales::split_tag($tag);
285 if ($t) {
286 if ( my $parent = Locales->new($l) ) {
287 no strict 'refs';
288 $_decimal_format_group = ${"Locales::DB::Language::${l}::misc_info"}{'cldr_formats'}->{'_decimal_format_group'};
289 $_decimal_format_decimal = ${"Locales::DB::Language::${l}::misc_info"}{'cldr_formats'}->{'_decimal_format_decimal'};
290 }
291 }
292 }
293
294 if ( !$_decimal_format_group || !$_decimal_format_decimal ) {
295
296 # not much we can (accuratly) do, I am open to suggestions :)
297 warn "'$tag' is missing one or both decimal format options: _decimal_format_group ($_decimal_format_group) or _decimal_format_decimal ($_decimal_format_decimal) ...";
298 if ( $_decimal_format_group eq ',' ) {
299 $_decimal_format_decimal = '.';
300 }
301 elsif ( $_decimal_format_group eq '.' ) {
302 $_decimal_format_decimal = ',';
303 }
304 elsif ( $_decimal_format_decimal eq ',' ) {
305 $_decimal_format_group = '.';
306 }
307 elsif ( $_decimal_format_decimal eq '.' ) {
308 $_decimal_format_group = ',';
309 }
310
311 # TODO: fallback to values in its numberSystem (e.g. <symbols numberSystem="latn">) (only trips up a few as of CLDR 2.0)
312 elsif ( $tag eq 'ak' || $tag eq 'mfe' || $tag eq 'ses' || $tag eq 'khq' || $tag eq 'wal' ) {
313 $_decimal_format_decimal = '.';
314 }
315
316 else {
317 warn "\tCould not make worst-case-best-effort defualt from the curretn value.";
318 }
319 }
320
321 my $_percent_format_percent = (
322 defined $symbols_index
323 ? (
324 ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'percentSign'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'percentSign'}{'content'}
325 : ref $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'percentSign'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'percentSign'}->[0]
326 : $raw_struct->{'numbers'}{'symbols'}[$symbols_index]{'percentSign'}
327 )
328 : (
329 ref $raw_struct->{'numbers'}{'symbols'}{'percentSign'} eq 'HASH' ? $raw_struct->{'numbers'}{'symbols'}{'percentSign'}{'content'}
330 : ref $raw_struct->{'numbers'}{'symbols'}{'percentSign'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'symbols'}{'percentSign'}->[0]
331 : $raw_struct->{'numbers'}{'symbols'}{'percentSign'}
332 )
333 )
334 || $fallback_lang_misc_info->{'cldr_formats'}{'_percent_format_percent'};
335 if ( !$_percent_format_percent ) {
336 my ( $l, $t ) = Locales::split_tag($tag);
337 if ($t) {
338 if ( my $parent = Locales->new($l) ) {
339 no strict 'refs';
340 $_percent_format_percent = ${"Locales::DB::Language::${l}::misc_info"}{'cldr_formats'}->{'_percent_format_percent'};
341 }
342 }
343 }
344
345 # $fallback_lang_misc_info->{'cldr_formats'}{'delimiters'} ||= {
346 # map {
347 # my $norm = $_;
348 # $norm = lcfirst($norm);
349 # $norm =~ s/([A-Z])/_\L$1\E/g;
350 # ($norm => $raw_struct->{'delimiters'}{$_})
351 # } keys %{ $raw_struct->{'delimiters'} }
352 # };
353
354 # if ( $tag eq 'pt_br' ) { use Data::Dumper; print Dumper( $tag, $fallback_lang_misc_info ) }
355
356 # ick
357 if ( ref( $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'} ) eq 'HASH' ) {
358 if ( $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'type'} eq 'short' ) {
359 delete $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'};
360 }
361 }
362 elsif ( ref( $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'} ) eq 'ARRAY' ) {
363 if ( $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'type'} eq 'short' ) {
364 shift @{ $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'} };
365 }
366 }
367
368 my $plural_form_entry = $plural_forms->{$tag};
369 if ( !$plural_form_entry ) {
370 my ($parent_tag) = Locales::split_tag($tag);
371 if ( $parent_tag ne $tag && exists $plural_forms->{$parent_tag} ) {
372 $plural_form_entry = $plural_forms->{$parent_tag};
373 }
374 else {
375 for my $fb ( @{$fallback} ) {
376 if ( exists $plural_forms->{$fb} && ref( $plural_forms->{$fb} ) ) {
377 $plural_form_entry = $plural_forms->{$fb};
378 last;
379 }
380 }
381 }
382 }
383
384 # DO NOT DO THIS: $plural_form_entry ||= $plural_forms->{'en'};
385
386 $lang_misc_info = {
387 'fallback' => $fallback,
388 'cldr_formats' => {
389 'decimal' => (
390 ref( $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'} ) eq 'ARRAY'
391 ? (
392 ref $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'decimalFormat'}{'pattern'} eq 'HASH' ? $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'decimalFormat'}{'pattern'}{'content'}
393 : ref $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'decimalFormat'}{'pattern'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'decimalFormat'}{'pattern'}->[0]
394 : $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}[0]{'decimalFormat'}{'pattern'}
395
396 )
397 : (
398 ref $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'} eq 'HASH' ? $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'}{'content'}
399 : ref $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'}->[0]
400 : $raw_struct->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'}
401 )
402 )
403 || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'decimal'} ),
404 '_decimal_format_group' => $_decimal_format_group,
405 '_decimal_format_decimal' => $_decimal_format_decimal,
406 'percent' => (
407 ref $raw_struct->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'} eq 'HASH' ? $raw_struct->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'}{'content'}
408 : ref $raw_struct->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'} eq 'ARRAY' ? $raw_struct->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'}->[0]
409 : $raw_struct->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'}
410 )
411 || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'percent'} ),
412 '_percent_format_percent' => $_percent_format_percent,
413 'territory' => $raw_struct->{'localeDisplayNames'}{'codePatterns'}{'codePattern'}{'territory'}{'content'}
414 || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'territory'} ),
415 'language' => $raw_struct->{'localeDisplayNames'}{'codePatterns'}{'codePattern'}{'language'}{'content'}
416 || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'language'} ),
417 'locale' => ( Encode::decode_utf8( ref( $raw_struct->{'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'} ) eq 'HASH' ? $raw_struct->{'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'}{'content'} : $raw_struct->{'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'} ) )
418 || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'locale'} ), # wx_yz has no name but wx does and xy may
419 # {'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'}{'localeSeparator'} => ', ' (not needed since we only use territory subtag)
420 'list' => {
421 '2' => $raw_struct->{'listPatterns'}{'listPattern'}{'listPatternPart'}{'2'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'list'}{'2'} ),
422 'end' => $raw_struct->{'listPatterns'}{'listPattern'}{'listPatternPart'}{'end'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'list'}{'end'} ),
423 'middle' => $raw_struct->{'listPatterns'}{'listPattern'}{'listPatternPart'}{'middle'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'list'}{'middle'} ),
424 'start' => $raw_struct->{'listPatterns'}{'listPattern'}{'listPatternPart'}{'start'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'list'}{'start'} ),
425 },
426 'ellipsis' => {
427
428 # Encode::decode_utf8() on current fallback will keep from tripping perl's hash value bytes string bug?
429 'final' => $raw_struct->{'characters'}{'ellipsis'}{'final'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'ellipsis'}{'final'} ),
430 'initial' => $raw_struct->{'characters'}{'ellipsis'}{'initial'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'ellipsis'}{'initial'} ),
431 'medial' => $raw_struct->{'characters'}{'ellipsis'}{'medial'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'cldr_formats'}{'ellipsis'}{'medial'} ),
432 },
433 },
434 'characters' => {
435 'more_information' => (
436 ref( $raw_struct->{'characters'}{'moreInformation'} ) eq 'HASH'
437 ? ( $raw_struct->{'characters'}{'moreInformation'}{'content'} || Encode::decode_utf8( $fallback_lang_misc_info->{'characters'}{'more_information'} ) )
438 : ( $raw_struct->{'characters'}{'moreInformation'} || Encode::decode_utf8( $fallback_lang_misc_info->{'characters'}{'more_information'} ) )
439 )
440 },
441 'delimiters' => {
442 map {
443 my $norm = $_;
444 $norm = lcfirst($norm);
445 $norm =~ s/([A-Z])/_\L$1\E/g;
446
447 # print Dumper(
448 # [
449 # $_,
450 # $norm,
451 # exists $raw_struct->{'delimiters'}{$_},
452 # $raw_struct->{'delimiters'}{$_},
453 # $fallback_lang_misc_info->{'cldr_formats'}{'delimiters'}{$norm}
454 # ]);
455 (
456 $norm => (
457 exists $raw_struct->{'delimiters'}{$_}
458 ? ( $raw_struct->{'delimiters'}{$_} || $fallback_lang_misc_info->{'delimiters'}{$norm} )
459 : $fallback_lang_misc_info->{'delimiters'}{$norm}
460 )
461 )
462 } ( 'quotationStart', 'quotationEnd', 'alternateQuotationStart', 'alternateQuotationEnd' )
463 },
464 'plural_forms' => {
465
466 # Order is important for Locale::Maketext::Utils::quant():
467 # one (singular), two (dual), few (paucal), many, other, zero
468 'category_list' => [
469 (
470 ( grep { exists $plural_form_entry->{$_} } ( Locales::get_cldr_plural_category_list() ) ),
471 exists $plural_form_entry->{'other'} ? () : ('other') # has to have 'other' at the end if no where else
472 )
473 ],
474 'category_rules' => $plural_form_entry,
475 },
476 'orientation' => {
477 'characters' => $raw_struct->{'layout'}{'orientation'}{'characters'} || $fallback_lang_misc_info->{'orientation'}{'characters'} || 'left-to-right',
478 'lines' => $raw_struct->{'layout'}{'orientation'}{'lines'} || $fallback_lang_misc_info->{'orientation'}{'lines'} || 'top-to-bottom',
479 },
480 'posix' => {
481 'yesstr' => $raw_struct->{'posix'}{'messages'}{'yesstr'} || Encode::decode_utf8( $fallback_lang_misc_info->{'posix'}{'yesstr'} ),
482 'nostr' => $raw_struct->{'posix'}{'messages'}{'nostr'} || Encode::decode_utf8( $fallback_lang_misc_info->{'posix'}{'nostr'} ),
483
484 # TODO: yesexp/noexp
485 },
486 };
487
488 for my $k ( keys %{ $lang_misc_info->{'delimiters'} } ) {
489 if ( ref( $lang_misc_info->{'delimiters'}{$k} ) eq 'HASH' ) {
490 $lang_misc_info->{'delimiters'}{$k} = $lang_misc_info->{'delimiters'}{$k}{'content'};
491 }
492 }
493
494 for my $lng ( sort keys %{ $raw_struct->{'localeDisplayNames'}{'languages'}{'language'} } ) {
495 next if $lng eq 'root';
496
497 # if ($tag eq 'en') {
498 # next if !get_xml_file_for($lng,1);
499 # }
500
501 my $short = $lng;
502 $short =~ tr/A-Z/a-z/;
503
504 my ( $l, $t, @x ) = split( /_/, $short );
505 next if @x;
506 next if $t && !exists $terr_code_to_name->{$t};
507
508 $lang_code_to_name->{$short} = $raw_struct->{'localeDisplayNames'}{'languages'}{'language'}{$lng}{'content'};
509 $lang_name_to_code->{ Locales::normalize_for_key_lookup( $raw_struct->{'localeDisplayNames'}{'languages'}{'language'}{$lng}{'content'} ) } = $short;
510 }
511
512 if ($fallback_lang_code_to_name) {
513 for my $fb_lng ( keys %{$fallback_lang_code_to_name} ) {
514 if ( !exists $lang_code_to_name->{$fb_lng} ) {
515 $lang_code_to_name->{$fb_lng} = $fallback_lang_code_to_name->{$fb_lng};
516 $lang_name_to_code->{ Locales::normalize_for_key_lookup( $fallback_lang_code_to_name->{$fb_lng} ) } = $fb_lng;
517 }
518 }
519 }
520 #### /Languages ####
521
522 # TOOD: ? merge in ant $raw_struct->{'fallback'} (sans language part of $tag or 'en' since those happen alreay) locale's ?
523
524 return ( $lang_code_to_name, $lang_name_to_code, $lang_misc_info, $terr_code_to_name, $terr_name_to_code );
525 }
526
527 sub write_language_module {
528 my ( $tag, $code_to_name, $name_to_code, $misc_info ) = @_;
529
530 # init 'category_rules_compiled' key
531 Locales::plural_rule_hashref_to_code( $misc_info->{'plural_forms'} );
532
533 my $code_to_name_str = _stringify_hash($code_to_name);
534 my $name_to_code_str = _stringify_hash($name_to_code);
535 my $misc_info_str;
536 {
537
538 # make values in plural_forms->category_rules_compiled be sub { ...} instead of 'sub \{ \.\.\. \}'
539 #
540 # this adds a package thing, maybe investigate?
541 # local $Data::Dumper::Deparse = 1;
542 # for my $k (keys %{$misc_info->{plural_forms}{category_rules_compiled}}) {
543 # print "RULE $k: $misc_info->{plural_forms}{category_rules_compiled}{$k}\n";
544 # $misc_info->{plural_forms}{category_rules_compiled}{$k} = eval "$misc_info->{plural_forms}{category_rules_compiled}{$k}";
545 # }
546
547 $misc_info_str = _stringify_hash($misc_info);
548
549 for my $k ( keys %{ $misc_info->{'plural_forms'}{category_rules_compiled} } ) {
550 $misc_info_str =~ s/(\'\Q$k\E\' \=\>) \"(sub\\ \\\{.*)\"/"$1" . String::Unquotemeta::unquotemeta("$2")/e;
551 }
552
553 # print "DEBUG:\n$misc_info_str\n";exit;
554 }
555 _write_utf8_perl(
556 "Language/$tag.pm", qq{package Locales::DB::Language::$tag;
557
558 use strict;
559 use warnings;
560
561 # Auto generated from CLDR
562 use if \$Locales::_UNICODE_STRINGS, 'utf8';
563
564 \$Locales::DB::Language::$tag\::VERSION = '$mod_version';
565
566 \$Locales::DB::Language::$tag\::cldr_version = '$cldr_version';
567
568 \%Locales::DB::Language::$tag\::misc_info = (
569 $misc_info_str,
570 );
571
572 \%Locales::DB::Language::$tag\::code_to_name = (
573 $code_to_name_str,
574 );
575
576 \%Locales::DB::Language::$tag\::name_to_code = (
577 $name_to_code_str,
578 );
579
580 1;
581 },
582 );
583 }
584
585 sub write_territory_module {
586 my ( $tag, $code_to_name, $name_to_code ) = @_;
587
588 my $code_to_name_str = _stringify_hash($code_to_name);
589 my $name_to_code_str = _stringify_hash($name_to_code);
590
591 _write_utf8_perl(
592 "Territory/$tag.pm", qq{package Locales::DB::Territory::$tag;
593
594 use strict;
595 use warnings;
596
597 # Auto generated from CLDR
598 use if \$Locales::_UNICODE_STRINGS, 'utf8';
599
600 \$Locales::DB::Territory::$tag\::VERSION = '$mod_version';
601
602 \$Locales::DB::Territory::$tag\::cldr_version = '$cldr_version';
603
604 \%Locales::DB::Territory::$tag\::code_to_name = (
605 $code_to_name_str,
606 );
607
608 \%Locales::DB::Territory::$tag\::name_to_code = (
609 $name_to_code_str,
610 );
611
612 1;
613
614 },
615 );
616
617 }
618
619 my @_get_fast_norm_test_data = ( '', 0 );
620
621 sub _get_fast_norm_test_data {
622 if ( $_get_fast_norm_test_data[1] == 0 ) {
623 my $loc = Locales->new();
624 my $cnt = 12;
625 for my $l ( sort $loc->get_language_codes() ) {
626 $_get_fast_norm_test_data[0] .= qq{is(\$self_obj->get_locale_display_pattern_from_code('$l'), \$self_obj->get_locale_display_pattern_from_code_fast('$l'), 'get_locale_display_pattern_from_code[_fast] same result for $l');\n};
627 $_get_fast_norm_test_data[1]++;
628
629 $_get_fast_norm_test_data[0] .= qq{is(\$self_obj->get_character_orientation_from_code('$l'), \$self_obj->get_character_orientation_from_code('$l'), 'get_character_orientation_from_code[_fast] same result for $l');\n};
630 $_get_fast_norm_test_data[1]++;
631
632 $_get_fast_norm_test_data[0] .= "\n";
633 }
634 }
635
636 return @_get_fast_norm_test_data;
637 }
638
639 sub write_locale_test {
640 my ($tag) = @_;
641
642 my ( $fast_norm_str, $fast_norm_cnt ) = _get_fast_norm_test_data();
643
644 _write_utf8_perl(
645 "../../../t/042.$tag.t", qq{
646 # Auto generated during CLDR build
647
648 use Test::More tests => 13 + $fast_norm_cnt;
649
650 use lib 'lib', '../lib';
651
652 BEGIN {
653 use_ok( 'Locales::DB::Language::$tag' );
654 use_ok( 'Locales::DB::Territory::$tag' );
655 }
656
657 diag( "Sanity checking Locales::DB::Language::$tag \$Locales::DB::Language::$tag\::VERSION DB" );
658
659 use Locales;
660 use Locales::DB::Language::en;
661 use Locales::DB::Territory::en;
662
663 my \@en_lang_codes = sort(keys \%Locales::DB::Language::en::code_to_name);
664 my \@en_terr_codes = sort(keys \%Locales::DB::Territory::en::code_to_name);
665
666 my \@my_lang_codes = sort(keys \%Locales::DB::Language::$tag\::code_to_name);
667 my \@my_terr_codes = sort(keys \%Locales::DB::Territory::$tag\::code_to_name);
668 my \%lang_lu;
669 my \%terr_lu;
670 \@lang_lu{ \@my_lang_codes } = ();
671 \@terr_lu{ \@my_terr_codes } = ();
672 ok(\$Locales::DB::Language::$tag\::cldr_version eq \$Locales::cldr_version, 'CLDR version is correct');
673 ok(\$Locales::DB::Language::$tag\::VERSION eq (\$Locales::VERSION - $v_offset), 'VERSION is correct');
674
675 ok(!(grep {!exists \$lang_lu{\$_} } \@en_lang_codes), '$tag languages contains en');
676 ok(!(grep {!exists \$terr_lu{\$_} } \@en_terr_codes), '$tag territories contains en');
677
678 my \%uniq = ();
679 grep { not \$uniq{\$_}++ } \@{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_list'} };
680 is_deeply(
681 [ sort \@{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_list'} }],
682 [ sort keys \%uniq ],
683 "'category_list' contains no duplicates"
684 );
685
686 ok(grep(m/^other\$/, \@{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_list'} }), "'category_list' has 'other'");
687
688 is_deeply(
689 [ grep !m/^other\$/, sort \@{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_list'} }],
690 [ grep !m/^other\$/, sort keys \%{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules'} } ],
691 "'category_rules' has necessary 'category_list' items"
692 );
693
694 is_deeply(
695 [ sort keys \%{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules'} } ],
696 [ sort keys \%{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules_compiled'} } ],
697 "each 'category_rules' has a 'category_rules_compiled'"
698 );
699 my \$ok_rule_count = 0;
700 my \$error = '';
701 for my \$rule (keys \%{\$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules_compiled'}}) {
702 if (ref(\$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules_compiled'}{\$rule}) eq 'CODE') {
703 \$ok_rule_count++;
704 next;
705 }
706 eval \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules_compiled'}{\$rule};
707 if (\$@) {
708 \$error .= \$@;
709 next;
710 }
711 else {
712 \$ok_rule_count++;
713 }
714 }
715 ok(\$ok_rule_count == keys \%{ \$Locales::DB::Language::$tag\::misc_info{'plural_forms'}->{'category_rules_compiled'} }, "each 'category_rules_compiled' eval without error - count");
716 is(\$error, '', "each 'category_rules_compiled' is a code ref or evals without error - errors");
717
718 my \$self_obj = Locales->new('$tag');
719 ok(ref(\$self_obj), '$tag object created OK');
720
721 $fast_norm_str
722
723 },
724 "t/042.$tag.t",
725 );
726 }
727
728 sub write_get_plural_form_test {
729 my ($tag) = @_;
730
731 my $loc = Locales->new($tag) || die die "Could not create object for $tag: \$@";
732
733 my $arg_tests_count = 2;
734 if ( $loc->get_plural_form(0) eq 'other' ) {
735 $arg_tests_count = 4;
736 }
737
738 _write_utf8_perl(
739 "../../../t/06.$tag.t", qq{
740 # Auto generated during CLDR build
741
742 use lib 'lib', '../lib';
743 use Test::More;
744
745 use Locales;
746
747 diag( "Verifying perl and js get_plural_form() behave the same for $tag." );
748
749 if (!\$ENV{'RELEASE_TESTING'}) {
750 plan 'skip_all' => 'These tests are only run under RELEASE_TESTING.';
751 }
752
753 my \$obj = Locales->new('$tag') || die "Could not create object for $tag: \$@";
754
755 my \@nums = ( 0, 1.6, 2.2, 3.14159, 42.78, 0 .. 256 );
756
757 eval 'use JE ()';
758 plan \$@ ? ( 'skip_all' => 'JE.pm required for testing JS/Perl plural behavior tests' ) : ( 'tests' => ( scalar(\@nums) * (4 + $arg_tests_count) ) );
759 my \$js = JE->new();
760
761 use File::Slurp;
762 my \$root = '.'; # TODO: make me portable
763 if ( -d '../share/' ) {
764 \$root = '..';
765 }
766 if ( !-d "\$root/share/" ) {
767 die "Can not determine share directory.";
768 }
769
770 my \@cats = map { "args_\$_" } \$obj->get_plural_form_categories();
771 my \$cats_args = join(', ', map { "'\$_'" } \@cats);
772
773 my \$jsfile = File::Slurp::read_file("\$root/share/functions/\$obj->{'locale'}.js") or die "Could not read '\$root/share/functions/\$obj->{'locale'}.js': \$!";
774
775 for my \$n (\@nums) {
776 my \$res = \$js->eval("var X = \$jsfile;return X.get_plural_form(\$n)");
777 is_deeply(
778 [ \$res->[0], \$res->[1] ], # have to do this to stringify JE object properly
779 [ \$obj->get_plural_form(\$n) ],
780 "perl and js get_plural_form() behave the same. Tag: \$obj->{'locale'} Number: \$n"
781 );
782 is(\$res->[1], 0, "using special is 0 for \$n (no args)");
783
784 my \$res_n = \$js->eval("var X = \$jsfile;return X.get_plural_form(-\$n)");
785 is_deeply(
786 [ \$res_n->[0], \$res_n->[1] ], # have to do this to stringify JE object properly
787 [ \$obj->get_plural_form("-\$n") ],
788 "perl and js get_plural_form() behave the same. Tag: \$obj->{'locale'} Number: -\$n"
789 );
790 is(\$res_n->[1], 0, "using special is 0 for -\$n (no args)");
791
792 my \$res_s = \$js->eval("var X = \$jsfile;return X.get_plural_form(\$n,\$cats_args)");
793 is_deeply(
794 [ \$res_s->[0], \$res_s->[1] ], # have to do this to stringify JE object properly
795 [ \$obj->get_plural_form(\$n,\@cats) ],
796 "perl and js get_plural_form() behave the same. Tag: \$obj->{'locale'} Number: \$n"
797 );
798 is(\$res_s->[1], 0, "using special is 0 for \$n (args w/ no spec zero)");
799
800 if ($arg_tests_count == 4) {
801 my \$res_n = \$js->eval("var X = \$jsfile;return X.get_plural_form(\$n, \$cats_args, 'spec_zeroth')");
802 is_deeply(
803 [ \$res_n->[0], \$res_n->[1] ], # have to do this to stringify JE object properly
804 [ \$obj->get_plural_form("\$n",\@cats, 'spec_zeroth') ],
805 "perl and js get_plural_form() behave the same. Tag: \$obj->{'locale'} Number: \$n"
806 );
807 my \$spec_bool = \$n == 0 ? 1 : 0;
808 is(\$res_n->[1], \$spec_bool, "using special is \$spec_bool for \$n (args w/ spec zero)");
809 }
810
811 # TODO: ? too many/too few args and check for carp ?
812 }
813 },
814 "t/06.$tag.t",
815 );
816 }
817
818 sub write_native_module {
819 my ( $native_map, $fallback_lookup ) = @_;
820
821 my $code_to_name_str = _stringify_hash_no_dumper($native_map);
822 my $fallback_lookup_str = _stringify_hash_no_dumper($fallback_lookup);
823
824 # nerd alert! TODO: verify during next build
825 if ( $code_to_name_str->{'tlh'} eq 'Klingon' ) { # i.e. no CLDR data for tlh
826
827 # "\x{f8e4}\x{f8d7}\x{f8dc}\x{f8d0}\x{f8db}"
828 # "\xef\xa3\xa4\xef\xa3\x97\xef\xa3\x9c\xef\xa3\x90\xef\xa3\x9b"
829 $code_to_name_str->{'tlh'} = ""; # need a font to see this, like Bengali
830 }
831
832 _write_utf8_perl(
833 "$locales_db/Native.pm", qq{package Locales::DB::Native;
834
835 use strict;
836 use warnings;
837
838 # Auto generated from CLDR
839 use if \$Locales::_UNICODE_STRINGS, 'utf8';
840
841 \$Locales::DB::Native::VERSION = '$mod_version';
842
843 \$Locales::DB::Native::cldr_version = '$cldr_version';
844
845 \%Locales::DB::Native::code_to_name = (
846 $code_to_name_str);
847
848 \%Locales::DB::Native::value_is_fallback = (
849 $fallback_lookup_str);
850
851 1;
852 },
853 'lib/Locales/DB/Native.pm',
854 1,
855 );
856 }
857
858 sub write_db_loadable_module {
859 my $en = Locales->new('en');
860
861 my $code_hr;
862 my $terr_hr;
863
864 for my $t ( $en->get_territory_codes() ) {
865 $terr_hr->{$t} = 1;
866 }
867
868 for my $c ( $en->get_language_codes() ) {
869 next if Locales::is_non_locale($c);
870
871 if ( Locales->new($c) ) {
872 $code_hr->{$c} = 1;
873 }
874 }
875
876 my $code_str = _stringify_hash_no_dumper($code_hr);
877 my $terr_str = _stringify_hash_no_dumper($terr_hr);
878
879 _write_utf8_perl(
880 "$locales_db/Loadable.pm", qq{package Locales::DB::Loadable;
881
882 use strict;
883 use warnings;
884
885 # Auto generated from CLDR
886 use if \$Locales::_UNICODE_STRINGS, 'utf8';
887
888 \$Locales::DB::Loadable::VERSION = '$mod_version';
889
890 \$Locales::DB::Loadable::cldr_version = '$cldr_version';
891
892 \%Locales::DB::Loadable::code = (
893 $code_str);
894
895 \%Locales::DB::Loadable::territory = (
896 $terr_str);
897
898 1;
899 },
900 'lib/Locales/DB/Loadable.pm',
901 1,
902 );
903
904 }
905
906 sub write_character_orientation_module {
907 my ( $text_direction_map, $fallback_lookup ) = @_;
908
909 my $code_to_name_str = _stringify_hash_no_dumper($text_direction_map);
910 my $fallback_lookup_str = _stringify_hash_no_dumper($fallback_lookup);
911
912 _write_utf8_perl(
913 "$locales_db/CharacterOrientation.pm", qq{package Locales::DB::CharacterOrientation;
914
915 use strict;
916 use warnings;
917
918 # Auto generated from CLDR
919 use if \$Locales::_UNICODE_STRINGS, 'utf8';
920
921 \$Locales::DB::CharacterOrientation::VERSION = '$mod_version';
922
923 \$Locales::DB::CharacterOrientation::cldr_version = '$cldr_version';
924
925 \%Locales::DB::CharacterOrientation::code_to_name = (
926 $code_to_name_str);
927
928 \%Locales::DB::CharacterOrientation::value_is_fallback = (
929 $fallback_lookup_str);
930
931 1;
932 },
933 'lib/Locales/DB/CharacterOrientation.pm',
934 1,
935 );
936
937 File::Path::Tiny::mk("$locales_db/CharacterOrientation") || die "Could not create '$locales_db/CharacterOrientation': $!";
938 my $rtl;
939 for my $name ( keys %{$text_direction_map} ) {
940 if ( $text_direction_map->{$name} eq 'right-to-left' ) {
941 $rtl->{$name} = undef();
942 }
943 elsif ( $text_direction_map->{$name} ne 'left-to-right' ) {
944 warn "$name is neither right-to-left or left-to-right";
945 }
946 }
947 die "Locales::DB::CharacterOrientation::Tiny lookup hash not built" if ref($rtl) ne 'HASH';
948 $rtl = _stringify_hash_no_dumper($rtl);
949
950 _write_utf8_perl(
951 "$locales_db/CharacterOrientation/Tiny.pm", qq{package Locales::DB::CharacterOrientation::Tiny;
952
953 use strict;
954 use warnings;
955
956 # Auto generated from CLDR
957 use if \$Locales::_UNICODE_STRINGS, 'utf8';
958
959 \$Locales::DB::CharacterOrientation::Tiny::VERSION = '$mod_version';
960
961 \$Locales::DB::CharacterOrientation::Tiny::cldr_version = '$cldr_version';
962
963 my \%rtl = (
964 $rtl);
965
966 sub get_orientation {
967 if ( exists \$rtl{ \$_[0] } ) {
968 return 'right-to-left';
969 }
970 else {
971 require Locales;
972 my (\$l) = Locales::split_tag(\$_[0]);
973 if (\$l ne \$_[0]) {
974 return 'right-to-left' if exists \$rtl{ \$l };
975 }
976 return 'left-to-right';
977 }
978 }
979
980 1;
981 },
982 'lib/Locales/DB/CharacterOrientation/Tiny.pm',
983 1,
984 );
985 }
986
987 sub write_name_pattern_module {
988 my ( $name_pattern, $isfallback ) = @_;
989
990 my $name_pattern_str = _stringify_hash_no_dumper($name_pattern);
991 my $fallback_lookup_str = _stringify_hash_no_dumper($isfallback);
992
993 _write_utf8_perl(
994 "$locales_db/LocaleDisplayPattern.pm", qq{package Locales::DB::LocaleDisplayPattern;
995
996 use strict;
997 use warnings;
998
999 # Auto generated from CLDR
1000 use if \$Locales::_UNICODE_STRINGS, 'utf8';
1001
1002 \$Locales::DB::LocaleDisplayPattern::VERSION = '$mod_version';
1003
1004 \$Locales::DB::LocaleDisplayPattern::cldr_version = '$cldr_version';
1005
1006 \%Locales::DB::LocaleDisplayPattern::code_to_pattern = (
1007 $name_pattern_str);
1008
1009 \%Locales::DB::LocaleDisplayPattern::value_is_fallback = (
1010 $fallback_lookup_str);
1011
1012 1;
1013 },
1014 'lib/Locales/DB/LocaleDisplayPattern.pm',
1015 1,
1016 );
1017
1018 # $locales_db/LocaleDisplayPattern
1019 File::Path::Tiny::mk("$locales_db/LocaleDisplayPattern") || die "Could not create '$locales_db/CharacterOrientation': $!";
1020
1021 my $name_pattern_hr;
1022
1023 require Locales::DB::Language::en;
1024 my $default_pattern = $Locales::DB::Language::en::misc_info{'cldr_formats'}{'locale'};
1025 for my $k ( keys %{$name_pattern} ) {
1026 next if !$name_pattern->{$k} || $name_pattern->{$k} =~ m/^\s+$/ || $name_pattern->{$k} eq $default_pattern;
1027 $name_pattern_hr->{$k} = $name_pattern->{$k};
1028 }
1029
1030 die "Locales::DB::LocaleDisplayPattern::Tiny lookup hash not built" if ref($name_pattern_hr) ne 'HASH';
1031 $name_pattern_hr = _stringify_hash_no_dumper($name_pattern_hr);
1032
1033 $default_pattern = quotemeta($default_pattern);
1034
1035 # $locales_db/LocaleDisplayPattern/Tiny.pm
1036 _write_utf8_perl(
1037 "$locales_db/LocaleDisplayPattern/Tiny.pm", qq{package Locales::DB::LocaleDisplayPattern::Tiny;
1038
1039 use strict;
1040 use warnings;
1041
1042 # Auto generated from CLDR
1043 use if \$Locales::_UNICODE_STRINGS, 'utf8';
1044
1045 \$Locales::DB::LocaleDisplayPattern::Tiny::VERSION = '$mod_version';
1046
1047 \$Locales::DB::LocaleDisplayPattern::Tiny::cldr_version = '$cldr_version';
1048
1049 my \%locale_display_lookup = (
1050 $name_pattern_hr);
1051
1052 sub get_locale_display_pattern {
1053 if ( exists \$locale_display_lookup{ \$_[0] } ) {
1054 return \$locale_display_lookup{ \$_[0] };
1055 }
1056 else {
1057 require Locales;
1058 my (\$l) = Locales::split_tag(\$_[0]);
1059 if (\$l ne \$_[0]) {
1060 return \$locale_display_lookup{\$l} if exists \$locale_display_lookup{ \$l };
1061 }
1062 return "$default_pattern";
1063 }
1064 }
1065
1066 1;
1067 },
1068 'lib/Locales/DB/LocaleDisplayPattern/Tiny.pm',
1069 1,
1070 );
1071 }
1072
1073 sub write_plural_forms_argument_pod {
1074 my ( $plural_forms, $isfallback ) = @_;
1075 File::Path::Tiny::mk("$locales_db/Docs") || die "Could not create '$locales_db/Docs': $!";
1076
1077 my $pod_starts = '__END__'; # this is to help prevent mis-parsing for CPAN like rt 76129 (probably not necessary)
1078 my $pkg = 'Locales::DB::Docs::PluralForms'; # this is to help prevent mis-parsing for CPAN like rt 76129
1079 my $pod_mark = '='; # this is to help prevent mis-parsing for CPAN like rt 80546 (and not fixed *again* in 0.28)
1080 my $pod_items = '';
1081
1082 for my $ent ( @{$plural_forms} ) {
1083
1084 if ( exists $isfallback->{ $ent->{'tag'} } ) {
1085 $pod_items .= "=item $ent->{'tag'}\n\nCLDR $cldr_version did not define data for “$ent->{'tag'}”, thus it will fallback to L</en> behavior.\n\nYou can L<submit the missing data to the CLDR|http://unicode.org/cldr/trac> if you wish.\n\n";
1086 }
1087 else {
1088 $pod_items .= "=item $ent->{'tag'}\n\n$fb get_plural_form(\$n, $ent->{'csv'})\n";
1089 if ( $ent->{'zero_is_not_other'} ) {
1090 $pod_items .= "\nNote: zero falls under a different category than “other” so there is no L</“Special Zero” Argument> for $ent->{'tag'}\n\n";
1091 }
1092 else {
1093 $pod_items .= " get_plural_form(\$n, $ent->{'csv'}, special_zero)\n\n";
1094 }
1095 }
1096 }
1097
1098 # $locales_db/Docs/PluralForms.pm
1099 _write_utf8_perl(
1100 "$locales_db/Docs/PluralForms.pm", qq{package $pkg;
1101
1102 use strict;
1103 use warnings;
1104
1105 # Auto generated from CLDR
1106 use if \$Locales::_UNICODE_STRINGS, 'utf8';
1107
1108 \$Locales::DB::Docs::PluralForms::VERSION = '$mod_version';
1109
1110 \$Locales::DB::Docs::PluralForms::cldr_version = '$cldr_version';
1111
1112 1;
1113
1114 $pod_starts
1115
1116 ${pod_mark}encoding utf-8
1117
1118 ${pod_mark}head1 NAME
1119
1120 Locales::DB::Docs::PluralForms - plural form details reference for all
1121 included locales
1122
1123 ${pod_mark}head1 VERSION
1124
1125 Locales.pm v$mod_version (based on CLDR v$cldr_version)
1126
1127 ${pod_mark}head1 DESCRIPTION
1128
1129 CLDR L<defines a set of broad plural categories and rules|http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html> that determine which category any given number will fall under.
1130
1131 L<Locales> allows you to determine the plural categories applicable to a specific locale and also which category a given number will fall under in that locale.
1132
1133 This POD documents which categories and in what order you'd specify them in additional arguments to L<Locales/get_plural_form()> (i.e. the optional arguments after the number).
1134
1135 ${pod_mark}head2 “Special Zero” Argument
1136
1137 In addition to the CLDR category value list you can also specify one additional argument of what to use for zero instead of the value for “other”.
1138
1139 This won't be used if 0 falls under a specific category besides “other”.
1140
1141 ${pod_mark}head1 Plural Category Argument Order Reference
1142
1143 ${pod_mark}over 4
1144
1145 $pod_items
1146
1147 ${pod_mark}back
1148
1149 ${pod_mark}head1 BUGS AND LIMITATIONS
1150
1151 Please see L<Locales/BUGS AND LIMITATIONS>
1152
1153 ${pod_mark}head2 BEFORE YOU SUBMIT A BUG REPORT
1154
1155 Please see L<Locales/BEFORE YOU SUBMIT A BUG REPORT>
1156
1157 ${pod_mark}head1 AUTHOR
1158
1159 Daniel Muey C<< <http://drmuey.com/cpan_contact.pl> >>
1160
1161 ${pod_mark}head1 LICENCE AND COPYRIGHT
1162
1163 Copyright (c) 2009, Daniel Muey C<< <http://drmuey.com/cpan_contact.pl> >>. All rights reserved.
1164
1165 This module is free software; you can redistribute it and/or
1166 modify it under the same terms as Perl itself. See L<perlartistic>.
1167
1168 ${pod_mark}head1 DISCLAIMER OF WARRANTY
1169
1170 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
1171 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
1172 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
1173 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
1174 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1175 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
1176 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
1177 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
1178 NECESSARY SERVICING, REPAIR, OR CORRECTION.
1179
1180 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1181 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
1182 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
1183 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
1184 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
1185 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
1186 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
1187 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
1188 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
1189 SUCH DAMAGES.
1190
1191 },
1192 'lib/Locales/DB/Docs/PluralForms.pm',
1193 1,
1194 );
1195 }
1196
1197 sub build_javascript_share {
1198 my ($tag) = @_;
1199
1200 if ( -d 'share/' ) {
1201 File::Path::Tiny::rm('share/') || die "Could not remove 'share/': $!";
1202 }
1203 for my $d (qw(misc_info/ functions/ code_to_name/ datetime/ db/)) {
1204 File::Path::Tiny::mk("share/$d") || die "Could not create 'share/$d': $!";
1205 }
1206
1207 my $loc = Locales->new();
1208 for my $tag ( sort $loc->get_language_codes() ) {
1209 my $tag_loc = Locales->new($tag) || next;
1210
1211 my $guts_m = $tag_loc->{'language_data'}{'misc_info'};
1212 for my $k ( keys %{ $guts_m->{'plural_forms'}{'category_rules_compiled'} } ) {
1213 $guts_m->{'plural_forms'}{'category_rules_compiled'}{$k} = Locales::plural_rule_string_to_javascript_code( $guts_m->{'plural_forms'}{'category_rules'}{$k}, $k );
1214 }
1215 my $json = JSON::Syck::Dump($guts_m); # no eval, lets just die
1216 $json =~ s/\"(function \(n\) \{)/$1/g;
1217 $json =~ s/(return\;\})\"/$1/g;
1218
1219 open( my $fh_m, '>', "share/misc_info/$tag.js" ) or die "Could not open 'share/misc_info/$tag.js': $!";
1220 print {$fh_m} $json;
1221 close $fh_m;
1222
1223 my $cats_list_js = JSON::Syck::Dump( $guts_m->{'plural_forms'}{'category_list'} );
1224 my $cats_proc_js = JSON::Syck::Dump( [ Locales::get_cldr_plural_category_list(1) ] );
1225 my $cats_rule_js = JSON::Syck::Dump( $guts_m->{'plural_forms'}{'category_rules_compiled'} );
1226 $cats_rule_js =~ s/"(function[^"]+)"/$1/g;
1227
1228 open( my $fh_f, '>', "share/functions/$tag.js" ) or die "Could not open 'share/functions/$tag.js': $!";
1229
1230 # var category_process_order = $cats_proc_js;
1231 # var category_rules_lookup = $cats_rule_js;
1232 # var categories = $cats_list_js;
1233
1234 my $js_code = <<"END_FUNC";
1235 {
1236 'get_plural_form' : function (n) {
1237 var category;
1238 var category_values = Array.prototype.slice.call(arguments,1);
1239
1240 var has_extra_for_zero = 0;
1241 var abs_n = Math.abs(n);
1242 var category_process_order = $cats_proc_js;
1243 var category_rules_lookup = $cats_rule_js;
1244
1245 for (i=0; i < category_process_order.length; i++) {
1246 if (category_rules_lookup[category_process_order[i]]) {
1247 category = category_rules_lookup[category_process_order[i]](abs_n);
1248 if (category) break;
1249 }
1250 }
1251
1252 var categories = $cats_list_js;
1253
1254 if ( category_values.length === 0 ) {
1255 category_values = categories; // no args will return the category name
1256 }
1257 else {
1258 var cat_len = categories.length;
1259 var val_len = category_values.length;
1260
1261 var cat_len_plus_one = cat_len + 1;
1262 if ( val_len === cat_len_plus_one ) {
1263 has_extra_for_zero++;
1264 }
1265 else if ( cat_len !== val_len ) {
1266 if (window.console) console.warn( 'The number of given values (' + val_len + ') does not match the number of categories (' + cat_len + ').' );
1267 }
1268 }
1269
1270 if ( category === undefined) {
1271 var cat_idx = has_extra_for_zero && abs_n !== 0 ? -2 : -1;
1272 var sliced = category_values.slice(cat_idx);
1273 return [sliced[0], has_extra_for_zero && abs_n === 0 ? 1 : 0];
1274 }
1275 else {
1276 var return_value;
1277 GET_POSITION:
1278 while(1) {
1279 var cat_pos_in_list;
1280 var index = -1;
1281 CATEGORY:
1282 for (i=0; i < categories.length; i++ ) {
1283 index++;
1284 if ( categories[i] === category ) {
1285 cat_pos_in_list = index;
1286 break CATEGORY;
1287 }
1288 }
1289
1290 if ( cat_pos_in_list === undefined && category !== 'other' ) {
1291 if (window.console) console.warn( 'The category (' + category + ') is not used by this locale.');
1292 category = 'other';
1293 continue GET_POSITION;
1294 }
1295 else if ( cat_pos_in_list === undefined) {
1296 var cat_idx = has_extra_for_zero && abs_n !== 0 ? -2 : -1;
1297 var sliced = category_values.slice(cat_idx);
1298 return_value = [sliced[0], has_extra_for_zero && abs_n === 0 ? 1 : 0]
1299 break GET_POSITION;
1300 }
1301 else {
1302 if ( has_extra_for_zero && category === 'other' ) {
1303 var cat_idx = has_extra_for_zero && abs_n === 0 ? -1 : cat_pos_in_list;
1304 var sliced = category_values.slice(cat_idx);
1305 return_value = [sliced[0], has_extra_for_zero && abs_n === 0 ? 1 : 0];
1306 break GET_POSITION;
1307 }
1308 else {
1309 return_value = [category_values[cat_pos_in_list], 0];
1310 break GET_POSITION;
1311 }
1312 }
1313 break GET_POSITION;
1314 }
1315
1316 return return_value;
1317 }
1318 }
1319 }
1320 END_FUNC
1321 print {$fh_f} JavaScript::Minifier::XS::minify($js_code);
1322 close $fh_f;
1323
1324 my $json_c = JSON::Syck::Dump( $tag_loc->{'language_data'}{'code_to_name'} ); # no eval, lets just die
1325
1326 open( my $fh_c, '>', "share/code_to_name/$tag.json" ) or die "Could not open 'share/code_to_name/$tag.json': $!";
1327 print {$fh_c} $json_c;
1328 close $fh_c;
1329
1330 my $dt_struct;
1331 my $dt_loc = eval { DateTime::Locale->load( Locales::normalize_tag_for_datetime_locale($tag) ) };
1332 if ($@) {
1333
1334 # Locales has $tag but DateTime::Locales does not (different CLDR version probably)
1335 print "$tag datetime JSON will be en: $@";
1336 $dt_loc = DateTime::Locale->load('en');
1337 }
1338
1339 for my $format (@dt_available_formats) {
1340 $dt_struct->{'format_for'}{$format} = $dt_loc->format_for($format); # no eval, should die since it means incomplete data
1341 }
1342 for my $meth (@dt_methods) {
1343 my $res = $dt_loc->$meth();
1344 $dt_struct->{$meth} =
1345 ref($res) eq 'ARRAY' ? [ @{$res} ]
1346 : ref($res) eq 'HASH' ? { %{$res} }
1347 : $res;
1348 }
1349
1350 my $json_d = JSON::Syck::Dump($dt_struct); # no eval, lets just die
1351 open( my $fh_d, '>', "share/datetime/$tag.json" ) or die "Could not open 'share/datetime/$tag.json': $!";
1352 print {$fh_d} $json_d;
1353 close $fh_d;
1354
1355 append_file( $manifest, "share/misc_info/$tag.js\nshare/code_to_name/$tag.json\nshare/datetime/$tag.json\nshare/functions/$tag.js\n" );
1356 }
1357
1358 require Locales::DB::Loadable;
1359 my $json_d = JSON::Syck::Dump( { 'code' => \%Locales::DB::Loadable::code, 'territory' => \%Locales::DB::Loadable::territory } ); # no eval, lets just die
1360 open( my $fh_d, '>', "share/db/loadable.json" ) or die "Could not open 'share/db/loadable.json': $!";
1361 print {$fh_d} $json_d;
1362 close $fh_d;
1363
1364 append_file( $manifest, "share/db/loadable.json" );
1365 }
1366
1367 sub build_manifest {
1368 my $base = $manifest;
1369 $base =~ s{\.build$}{};
1370 my @in = read_file("$base.in");
1371 my @bl = read_file("$base.build");
1372 write_file( $base, @in, @bl );
1373 }
1374
1375 sub do_changelog {
1376 my $changelog = $manifest;
1377 $changelog =~ s{MANIFEST\.build$}{Changes};
1378 my @cl = read_file($changelog);
1379 return if grep /^$Locales::VERSION\s+/, @cl;
1380
1381 my $time = localtime();
1382 my $new_ent = <<"END_CL";
1383 $Locales::VERSION $time
1384 - Updated data to CLDR $Locales::cldr_version
1385
1386 END_CL
1387 write_file( $changelog, $new_ent, @cl );
1388 }
1389
1390 sub _write_utf8_perl {
1391 my ( $file, $guts, $mani, $open_plain ) = @_;
1392
1393 my $open = $open_plain ? '>' : '>:utf8'; #:utf8 breaks Native.pm
1394
1395 open( my $fh, $open, $file ) or die "Could not open '$file': $!";
1396 print {$fh} $guts;
1397 close $fh;
1398
1399 system( qw(perltidy -b), $file ) == 0 || die "perltidy failed, '$file' probably has syntax errors";
1400 unlink "$file.bak";
1401
1402 append_file( $manifest, $mani ? "$mani\n" : "lib/Locales/DB/$file\n" );
1403 }
1404
1405 sub _stringify_hash_no_dumper {
1406 my $string;
1407 for my $k ( keys %{ $_[0] } ) {
1408 my $qk = $k;
1409 my $qv = $_[0]->{$k};
1410 $qk =~ s{\'}{\\\'}g;
1411 $qv =~ s{\'}{\\\'}g;
1412 my $ky = $k ne $qk ? qq{"$qk"} : qq{'$k'};
1413 my $vl = $_[0]->{$k} ne $qv ? qq{"$qv"} : qq{'$_[0]->{$k}'};
1414 $string .= "$ky => $vl,\n";
1415 }
1416 return $string;
1417 }
1418
1419 sub _stringify_hash {
1420 my $string = Dumper( $_[0] );
1421 $string =~ s/^\s*\{\s*//;
1422 $string =~ s/\s*\}\s*$//;
1423 return $string;
1424 }
1425
1426 1;
0 #!/usr/bin/perl
1
2 use lib '_build';
3 use _locales_build_utils;
4
5 my ( $cldr_db_path, $locales_db, $manifest ) = _locales_build_utils::init_paths_from_argv();
6
7 File::Path::Tiny::rm($locales_db) || die "Could not remove '$locales_db': $!";
8 File::Path::Tiny::mk($locales_db) || die "Could not create '$locales_db': $!";
9
10 unlink $manifest;
11 die "Could not clear '$manifest': $!" if -e $manifest;
12
13 chdir $locales_db || die "Could not change into '$locales_db': $!";
14
15 unlink glob('../../../t/042.*.t');
16 unlink glob('../../../share/*/*');
17
18 for my $type qw(Language Territory) {
19 File::Path::Tiny::mk($type) || die "Could not create '$type': $!";
20 }
21
22 my @root = _locales_build_utils::get_target_structs_from_cldr_for_tag( 'root', {}, {}, {} );
23
24 my ( $lang_code_to_name, $lang_name_to_code, $lang_misc_info, $terr_code_to_name, $terr_name_to_code ) = _locales_build_utils::get_target_structs_from_cldr_for_tag( 'en', @root[ 0, 3, 2 ] ) or die "Could not get data for 'en'";
25
26 _locales_build_utils::write_language_module( 'en', $lang_code_to_name, $lang_name_to_code, $lang_misc_info );
27
28 _locales_build_utils::write_territory_module( 'en', $terr_code_to_name, $terr_name_to_code );
29
30 _locales_build_utils::write_locale_test('en');
31
32 _locales_build_utils::write_get_plural_form_test('en');
0 #!/usr/bin/perl
1
2 use lib '_build';
3 use _locales_build_utils;
4
5 my ( $cldr_db_path, $locales_db ) = _locales_build_utils::init_paths_from_argv();
6
7 print "Starting 'en' ...\n";
8 system( './_build/cldr2en', $cldr_db_path, $locales_db ) == 0 || die "Could not build 'en'";
9
10 require Locales::DB::Language::en;
11
12 my $text_direction_map = {
13 'en' => $Locales::DB::Language::en::misc_info{'orientation'}{'characters'},
14 };
15 my $native_map = {
16 'en' => $Locales::DB::Language::en::code_to_name{'en'},
17 };
18 my $name_pattern = {
19 'en' => $Locales::DB::Language::en::misc_info{'cldr_formats'}{'locale'},
20 };
21
22 my %isfallback;
23 my @plural_forms;
24 for my $tag ( sort keys %Locales::DB::Language::en::code_to_name ) {
25 if ( $tag eq 'en' ) {
26 my $en = Locales->new('en');
27 push @plural_forms, { 'tag' => $tag, 'csv' => join( ', ', $en->get_plural_form_categories() ), 'zero_is_not_other' => ( $en->get_plural_form(0) ne 'other' ? 1 : 0 ) };
28 next;
29 }
30
31 print "Starting '$tag' ...\n";
32 if ( _locales_build_utils::get_xml_file_for( $tag, 1 ) ) {
33 system( './_build/en2mod', $cldr_db_path, $locales_db, $tag ) == 0 || die "Could not build '$tag'";
34 }
35 else {
36 print "No XML file for $tag\n";
37 }
38
39 if ( my $loc = Locales->new($tag) ) {
40 no strict 'refs';
41 $text_direction_map->{$tag} = ${"Locales::DB::Language::$tag\::misc_info"}{'orientation'}{'characters'};
42 $native_map->{$tag} = $loc->get_language_from_code($tag);
43 $name_pattern->{$tag} = ${"Locales::DB::Language::$tag\::misc_info"}{'cldr_formats'}{'locale'};
44 push @plural_forms, { 'tag' => $tag, 'csv' => join( ', ', $loc->get_plural_form_categories() ), 'zero_is_not_other' => ( $loc->get_plural_form(0) ne 'other' ? 1 : 0 ) };
45 }
46 else {
47 $text_direction_map->{$tag} = $text_direction_map->{'en'}; # default to 'en' since $tag has no data in CLDR
48 $native_map->{$tag} = $Locales::DB::Language::en::code_to_name{$tag}; # default to 'en' since $tag has no data in CLDR
49 $name_pattern->{$tag} = $Locales::DB::Language::en::misc_info{'cldr_formats'}{'locale'}; # default to 'en' since $tag has no data in CLDR
50 push @plural_forms, { 'tag' => $tag };
51 $isfallback->{$tag} = 1;
52 }
53 }
54
55 _locales_build_utils::write_native_module( $native_map, $isfallback );
56
57 _locales_build_utils::write_character_orientation_module( $text_direction_map, $isfallback );
58
59 _locales_build_utils::write_name_pattern_module( $name_pattern, $isfallback );
60
61 _locales_build_utils::write_plural_forms_argument_pod( \@plural_forms, $isfallback );
62
63 _locales_build_utils::write_db_loadable_module();
64
65 _locales_build_utils::build_javascript_share();
66
67 _locales_build_utils::build_manifest();
68
69 _locales_build_utils::do_changelog();
0 #!/usr/bin/perl
1
2 use lib '_build';
3 use _locales_build_utils;
4
5 my ( $cldr_db_path, $locales_db, $manifest ) = _locales_build_utils::init_paths_from_argv();
6
7 # use Data::Dumper;print Dumper($_locales_build_utils::plural_forms);
8
9 chdir $locales_db || die "Could not change into '$locales_db': $!";
10
11 my $tag = Locales::normalize_tag( $ARGV[2] );
12 my ( $l, $t ) = Locales::split_tag($tag);
13
14 my @root;
15 if ( $l ne $tag ) {
16 print "Fetching root for $tag ($l)\n";
17 @root = ( _locales_build_utils::get_target_structs_from_cldr_for_tag( $l, {}, {}, {} ) )[ 0, 3, 2 ];
18
19 # use Data::Dumper;print Dumper($root[2]);
20 }
21
22 require Locales::DB::Language::en;
23 require Locales::DB::Territory::en;
24
25 if (@root) {
26
27 # merge \%Locales::DB::Language::en::code_to_name into $root[0]
28 for my $k ( keys %Locales::DB::Language::en::code_to_name ) {
29 if ( !exists $root[0]->{$k} ) {
30 $root[0]->{$k} = $Locales::DB::Language::en::code_to_name{$k};
31 }
32 }
33
34 # merge \%Locales::DB::Territory::en::code_to_name into $root[1]
35 for my $k ( keys %Locales::DB::Territory::en::code_to_name ) {
36 if ( !exists $root[1]->{$k} ) {
37 $root[1]->{$k} = $Locales::DB::Territory::en::code_to_name{$k};
38 }
39 }
40
41 # merge \%Locales::DB::Language::en::misc_info into $root[2]
42
43 # use Data::Dumper;
44 # print Dumper( [ 'pre-merge', $root[2] ] );
45 $root[2] = _locales_build_utils::merge_hash( $root[2], \%Locales::DB::Language::en::misc_info );
46
47 # use Data::Dumper;
48 # print Dumper( [ 'pst-merge', $root[2] ] );
49
50 # $root[2] = {
51 # # 'fallback' => $fallback,
52 # # 'cldr_formats' => {
53 # # 'decimal' => $root[2]->{'numbers'}{'decimalFormats'}{'decimalFormatLength'}{'decimalFormat'}{'pattern'} || $Locales::DB::Language::en::misc_info{'cldr_formats'}{'decimal'},
54 # # 'percent' => $root[2]->{'numbers'}{'percentFormats'}{'percentFormatLength'}{'percentFormat'}{'pattern'} || $Locales::DB::Language::en::misc_info{'cldr_formats'}{'percent'},
55 # # 'territory' => $root[2]->{'localeDisplayNames'}{'codePatterns'}{'codePattern'}{'territory'}{'content'} || $Locales::DB::Language::en::misc_info{'cldr_formats'}{'territory'},
56 # # 'language' => $root[2]->{'localeDisplayNames'}{'codePatterns'}{'codePattern'}{'language'}{'content'} || $Locales::DB::Language::en::misc_info{'cldr_formats'}{'language'},
57 # # 'locale' => $root[2]->{'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'} || $Locales::DB::Language::en::misc_info{'cldr_formats'}{'locale'}, # wx_yz has no name but wx does and xy may
58 # # # {'localeDisplayNames'}{'localeDisplayPattern'}{'localePattern'}{'localeSeparator'} => ', ' (not needed since we only use territory subtag)
59 # # },
60 # # 'orientation' => {
61 # # 'characters' => $root[2]->{'layout'}{'orientation'}{'characters'} || $Locales::DB::Language::en::misc_info{'orientation'}{'characters'} || 'left-to-right',
62 # # 'lines' => $root[2]->{'layout'}{'orientation'}{'lines'} || $Locales::DB::Language::en::misc_info{'orientation'}{'lines'} || 'top-to-bottom',
63 # # },
64 # # 'posix' => {
65 # # 'yesstr' => $root[2]->{'posix'}{'messages'}{'yesstr'} || $Locales::DB::Language::en::misc_info{'posix'}{'yesstr'},
66 # # 'nostr' => $root[2]->{'posix'}{'messages'}{'nostr'} || $Locales::DB::Language::en::misc_info{'posix'}{'nostr'},
67 # # # TODO: yesexp/noexp
68 # # },
69 # };
70 }
71 else {
72 @root = ( \%Locales::DB::Language::en::code_to_name, \%Locales::DB::Territory::en::code_to_name, \%Locales::DB::Language::en::misc_info );
73 }
74
75 print "Fetching tag $tag\n";
76 my ( $lang_code_to_name, $lang_name_to_code, $lang_misc_info, $terr_code_to_name, $terr_name_to_code ) = _locales_build_utils::get_target_structs_from_cldr_for_tag( $tag, @root ) or die "Could not get data for '$tag'";
77
78 _locales_build_utils::write_language_module( $tag, $lang_code_to_name, $lang_name_to_code, $lang_misc_info );
79
80 _locales_build_utils::write_territory_module( $tag, $terr_code_to_name, $terr_name_to_code );
81
82 _locales_build_utils::write_locale_test($tag);
83
84 _locales_build_utils::write_get_plural_form_test($tag);
0 liblocales-perl (0.34+git20180627.1.d00f65b+ds-1) UNRELEASED; urgency=low
1
2 * New upstream snapshot.
3
4 -- Debian Janitor <janitor@jelmer.uk> Fri, 20 Jan 2023 06:55:20 -0000
5
06 liblocales-perl (0.34+ds-3) unstable; urgency=medium
17
28 [ Debian Janitor ]