diff --git a/src/club/without/dereku/itemtooltips/ItemTooltips.java b/src/club/without/dereku/itemtooltips/ItemTooltips.java index 92808be..fdf8bcd 100644 --- a/src/club/without/dereku/itemtooltips/ItemTooltips.java +++ b/src/club/without/dereku/itemtooltips/ItemTooltips.java @@ -32,7 +32,7 @@ import java.util.Properties; import java.util.logging.Level; import java.util.stream.Collectors; -import org.bukkit.configuration.InvalidConfigurationException; +import org.apache.commons.io.FileUtils; import org.bukkit.plugin.java.JavaPlugin; /** @@ -43,7 +43,6 @@ public class ItemTooltips extends JavaPlugin { public final Properties keys = new Properties(); private String language; - private ResourceDownloader rd; public List worlds; @Override @@ -53,7 +52,7 @@ public void onEnable() { if (!this.language.equals("en_US")) { //TODO - this.downloadAndApplyLanguage("", this.language); + this.downloadAndApplyLanguage(this.language); } this.worlds = this.getConfig().getStringList("worlds"); @@ -80,14 +79,13 @@ public void onEnable() { this.getLogger().info("Enabled."); } - public void downloadAndApplyLanguage(String version, String lang) { - File file = new File(this.getDataFolder().toString() + File.separator + "lang" + File.separator + version, lang + ".lang"); + public void downloadAndApplyLanguage(String lang) { + File file = FileUtils.getFile(this.getDataFolder().toString(), "lang", lang + ".lang"); if (!file.exists()) { - file.mkdir(); + file.getParentFile().mkdirs(); try { - this.rd = new ResourceDownloader(this); - this.rd.downloadResource(version, lang, file); - } catch (IOException | InvalidConfigurationException | IllegalArgumentException ex) { + new ResourceDownloader(this).downloadResource(lang, file); + } catch (IOException | IllegalArgumentException ex) { this.getLogger().log(Level.WARNING, "Failed to download " + file.getName(), ex); this.getLogger().log(Level.WARNING, "Using en_US language."); this.keys.clear(); diff --git a/src/club/without/dereku/itemtooltips/Listeners.java b/src/club/without/dereku/itemtooltips/Listeners.java index 2246b6f..d735e58 100644 --- a/src/club/without/dereku/itemtooltips/Listeners.java +++ b/src/club/without/dereku/itemtooltips/Listeners.java @@ -64,15 +64,9 @@ public Listeners(ItemTooltips aThis) throws ClassNotFoundException, SecurityExce this.plugin.getConfig().getString("format.withoutAmount", "%name%") ); - String pckg = Arrays.stream(Package.getPackages()) - .filter(pk -> pk.getName().startsWith("net.minecraft.server")) - .map(pk -> pk.getName()).findFirst().orElse(null); - - if (pckg == null) { - throw new RuntimeException("Failed to recognize nms version."); - } - - String nmsVersion = pckg.substring(21); + String pckg = aThis.getServer().getClass().getPackage().getName(); + String nmsVersion = pckg.substring(pckg.lastIndexOf('.') + 1); + this.nmsItemStack = ClassUtils.getClass("net.minecraft.server." + nmsVersion + ".ItemStack"); this.obcbCraftItemStack = ClassUtils.getClass("org.bukkit.craftbukkit." + nmsVersion + ".CraftItemStack"); this.asNMSCopy = this.obcbCraftItemStack.getMethod("asNMSCopy", ItemStack.class); diff --git a/src/club/without/dereku/itemtooltips/ResourceDownloader.java b/src/club/without/dereku/itemtooltips/ResourceDownloader.java index 8799a83..ce31ace 100644 --- a/src/club/without/dereku/itemtooltips/ResourceDownloader.java +++ b/src/club/without/dereku/itemtooltips/ResourceDownloader.java @@ -23,16 +23,18 @@ */ package club.without.dereku.itemtooltips; +import com.google.gson.Gson; +import com.google.gson.internal.LinkedTreeMap; +import com.google.gson.stream.JsonReader; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.logging.Level; import org.apache.commons.io.FileUtils; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; /** * @@ -40,40 +42,118 @@ */ public class ResourceDownloader { + private final static String VERSIONS_LIST = "https://launchermeta.mojang.com/mc/game/version_manifest.json"; private final static String ASSETS_URL = "http://resources.download.minecraft.net/"; + private final Gson gson = new Gson(); private final ItemTooltips plugin; - private final FileConfiguration configuration = new YamlConfiguration(); - public ResourceDownloader(ItemTooltips plugin) throws IOException, InvalidConfigurationException { + public ResourceDownloader(ItemTooltips plugin) { this.plugin = plugin; - try (InputStreamReader isr = new InputStreamReader(plugin.getResource("hashs.yml"))) { - this.configuration.load(isr); - } } /** * Download locale file. - * @param version version of assets - * @param name Name of resource. Ex.: ru_RU, en_CA, etc. + * + * @param locale Name of resource. Ex.: ru_RU, en_CA, etc. * @param destination Destination where to store file. * @throws MalformedURLException - * @throws IOException + * @throws IOException */ - public void downloadResource(String version, String name, File destination) throws MalformedURLException, IOException { - String hash; - if ((hash = this.configuration.getString(version + "." + name)) == null) { - throw new IllegalArgumentException("Resource with name \"" + name + "\" does not exists!"); + public void downloadResource(String locale, File destination) throws MalformedURLException, IOException { + URL versionList = new URL(ResourceDownloader.VERSIONS_LIST); + + VersionManifest vm; + try ( + InputStream inputStream = versionList.openConnection().getInputStream(); + InputStreamReader r = new InputStreamReader(inputStream); + JsonReader jr = new JsonReader(r) + ) { + vm = this.gson.fromJson(jr, VersionManifest.class); //I hope this will works + } + RemoteClient latestRelease = vm.getLatestRelease(); + URL assetsUrl = new URL(latestRelease.getUrl()); + + AssetIndex ai; + try ( + InputStream inputStream = assetsUrl.openConnection().getInputStream(); + InputStreamReader r = new InputStreamReader(inputStream); + JsonReader jr = new JsonReader(r) + ) { + ai = this.gson.fromJson(jr, AssetIndex.class); //I hope this will works too } - this.plugin.getLogger().log(Level.INFO, "Downloading {0}.lang (hash: {1})", new Object[]{name, hash}); + String hash = ai.getLocaleHash(locale); + this.plugin.getLogger().log(Level.INFO, "Downloading {0}.lang (hash: {1})", new Object[]{locale, hash}); FileUtils.copyURLToFile(new URL(ResourceDownloader.ASSETS_URL + this.createPathFromHash(hash)), destination); } /** - * From Mojang, with love. + * From Mojang, with love. + * * @param hash - * @return + * @return */ private String createPathFromHash(String hash) { return hash.substring(0, 2) + "/" + hash; } + + /* + Gson serialization + */ + class VersionManifest { + + LinkedTreeMap latest; + ArrayList versions; + + public RemoteClient getLatestRelease() { + String release = this.latest.get("release"); + for (RemoteClient c : this.versions) { + if (c.getId().equals(release)) { + return c; + } + } + + throw new IllegalArgumentException(release + " does not exists. There something is definitely wrong."); + } + } + + class RemoteClient { + + String id, url; + Object type, time, releaseTime; + + public String getId() { + return id; + } + + public String getUrl() { + return url; + } + } + + class ClientVersion { + + LinkedTreeMap assetIndex; + Object assets, downloads, id, libraries, logging, mainClass; + Object minecraftArguments, minimumLauncherVersion, releaseTime; + Object time, type; + + public String getAssetUrl() { + return this.assetIndex.get("url"); + } + } + + class AssetIndex { + + private final static String PATH = "minecraft/lang/%s.lang"; + LinkedTreeMap> objects; + + public String getLocaleHash(String locale) { + LinkedTreeMap asset + = this.objects.get(String.format(PATH, locale.toLowerCase())); + if (asset == null) { + throw new IllegalArgumentException("Locale " + locale + " does not exists!"); + } + return asset.get("hash"); + } + } } diff --git a/src/hashs.yml b/src/hashs.yml deleted file mode 100644 index 29829a4..0000000 --- a/src/hashs.yml +++ /dev/null @@ -1,349 +0,0 @@ -'1.8': - af_ZA: "974c91d46902f201f5b99826037f7c3891d5f6fd" - ar_SA: "ee4232cbe10c23b9aff88e9134dc0ae15a449de2" - ast_ES: "1d37a6f67db63ee15ec19f0426a914882bc9aadc" - az_AZ: "37821cab823859768abfebb8264953ee7e069c17" - bg_BG: "99d9280970ffd4a42b43f377f8d3e361d7f59bb7" - ca_ES: "a20c4251d6a7bf003f9e16654c70a2a5765819fd" - cs_CZ: "102b886329cc6f8376684d79e0275ec93de101ce" - cy_GB: "9f8f2bcb36ae3fe3c01bea418f33de3da2a6cc50" - da_DK: "6f17ad81a2a86f2152f50e4f6b89f67c097b7471" - de_DE: "0980bf808e738eeac691559f771e68bbd23c6d98" - el_GR: "a2a737070bd9d9fb62b7b849479d9ec49c51c3eb" - en_AU: "a23bceb1d6e6412dafbd5e49a1c05918854bdfc2" - en_CA: "af958233a71ccf73edc89e3b431a7a10e16cc1ac" - en_GB: "03f31164d234f10a3230611656332f1756e570a9" - en_PT: "64f5643da27da4218b87fae8352cbd65e98a6494" - eo_UY: "7c272cf1c8f3dcd0428ab75087890c8aa290812f" - es_AR: "ec9df689ff3737cdd03762ceaf934cba703b05cc" - es_ES: "7035158dd5e4b632403af3697eb8e78908b17ba2" - es_ES: "7035158dd5e4b632403af3697eb8e78908b17ba2" - es_MX: "fe8073cc2c07af629577017d78aeb2cc3c231dc8" - es_VE: "109ff111fef689c7435a612cee9becf47a7c701d" - es_YU: "655aeb17af37eed92c8fcf8b1c22b173eb76b561" - et_EE: "b0063e6fcabaab3428bd961204a94ca062110186" - eu_ES: "be945eb046d29e0215a0f35ef8973478eb2fc1d3" - fa_IR: "2740cd3806cec3b8c8895e31dd6a09e7925d1415" - fi_FI: "ced868873c0873349fc4274255a553a073a1d530" - fil_PH: "e2c8f26c91005a795c08344d601b10c84936e89d" - fr_CA: "a1d8cf2a5a4f536b15bb6481c7f0203b7dd1c58b" - fr_FR: "f9e1e61d35c4b8583a8d32bb9854f02f3a7bb7a8" - ga_IE: "fc70f364f2b5a1777255020444b74d25e28ef12d" - gl_ES: "15eccc77f642260b1d1904593306f20305147702" - gv_IM: "a742af8f9e453973b805ed6fff21a8bf9452bd9f" - he_IL: "fa68dfda0324e8ee58d40df5e9e7272f0d59c47a" - hi_IN: "b4e155c85e53f55354f5b51e7f7a35b11bd0a79c" - hr_HR: "a791d82f586d7b4f698bb7d47f07d4f7f002ce73" - hu_HU: "b7b754f6be6dcfcf1399c95aae35e44ffb9d66ad" - hy_AM: "81b2c1409d080d3a0f11296b1e497dd4b01c77ca" - id_ID: "2e3e328276f15e77119ade2529e7beafb0d69fd6" - is_IS: "a7b7e23172e3d8128cf1bf2140254bd71273e5b7" - it_IT: "0d4d1008e189d336b078f0fc97bb5a7a378a1966" - ja_JP: "0ca3e647521ee34e6fae49086e7cc192a148bca6" - ka_GE: "f1bc2dfa0c992be3e7480229c45830293ee19d08" - ko_KR: "515d2dc1517b1907c72a79e758ef995a3b54aab1" - kv_GB: "26ad90a5dc52f95e4802ae30422d2fb20edf5eba" - la_LA: "965fbbc622abd91585b1b5d40b045e384c5f1613" - lb_LU: "2ecf8694343c62a0d0e3ca3d9dc130067adf1c4d" - lt_LT: "fd264fd12e1b982d22954163a12b35825ae6a87a" - lv_LV: "9dc05d0d7c2bb7e6e73a1d8e2bc50e48746a6883" - mi_NZ: "e0e3a6eeb73178da894c84eb9d495128ab463a0d" - ms_MY: "b5a91fefb72e3664024e87ae64ef19977fe09003" - mt_MT: "e1cad7ce1c9feb8b7f56954e7f6f1d846de12c47" - nds_DE: "15a1256703dc94ce8ebf855e0b8dc6e235aa8615" - nl_NL: "dedc1cc7ded0d917b0fa2a34ad6b7843c5ffa46a" - nn_NO: "e952e5c34abdd0147fa5bb20c7fd4aa14353fd90" - no_NO: "42394caf96f31a1dd2b262ff52ee0a5ee3cfbd83" - oc_FR: "94ee6c08de62aa80f920b45329ba14d12f345f70" - pl_PL: "621cf443ebb4f183056625337a83c989f46c1822" - pt_BR: "eba6a289fd6815c89c8c35277c6775723621cfd7" - pt_PT: "7b243164dfca23d30a01763a9f26ab1863932ac2" - qya_AA: "e36314cb77ccca5fce96fa6b28c61d4efe859f0a" - ro_RO: "bbaf3f7aad0587fcf2797119eef34bac069fe411" - ru_RU: "dfb8059176413255e670b9cc82ad1f62ab5bd057" - se_NO: "757435c189f31d5c8db94a4adbc56c70a8998204" - sk_SK: "faf036a00abc60f858e841d04b9cbf96be4d804e" - sl_SI: "d8db0eb0c818256908e98efb1a681bc89ee19c04" - sr_SP: "87d4c7476672d23170c057c95a80ec1cba06a48a" - sv_SE: "37cba9315ce8202c834a94bdc92bed0879ed2d07" - th_TH: "1c839a4420005d136b55810e2dacf47eb588e2fa" - tlh_AA: "f5571f58e5ee9737b6de97a70ab6f8cc0b4172bb" - tr_TR: "2862fb39b282f3ae2bbee03ab91c8941b403494c" - uk_UA: "aaf1358fc98f0d7ddb3f0be043f6e2627a382f22" - val_ES: "1d6bad6f31c6797391e8c127c9b469be01ee9292" - vi_VN: "35aeb4279d6e6dfe134d2f385b4e6c7b8a06e7d4" - zh_TW: "7cfcba8a3f4a60d37a828cfff5aa3978bd28f19b" - zn_CN: "99b470341f0ae1a62c7d50dcaede34a907db7af6" -'1.9': - af_ZA: 5cd1c556c035502858a59c0788cfe11d3170ba75 - ar_SA: 25b71296317052cdd2751a5b931af1329254d6f9 - ast_ES: b57af170888588289a19592e15ead05b2a3f4e93 - az_AZ: e8d0382c6e1feb47539295d5d013431adf5f3d60 - be_BY: 66ed9b4b19593b8d6abab496bf7a36732b49e664 - bg_BG: 0f0ec42156a4fe37700fad9e85ed2445deb1b37a - br_FR: 999a1d3cfdb26d9d616f69ca92a4fb383122c0be - ca_ES: cdc419d81ccbd3fd35a9ab4ec3c1cad4043c2c0c - cs_CZ: 0a033f5de8753751979c685a858975ab88db323b - cy_GB: 55ef9f5c3bbea4194f2588db1f53a5712d33c5db - da_DK: 115ad1606ef44688b6bf85982fc7c6485e76734f - de_DE: c9a42fbd91bf118276ba8c03af13e80fcb9e8f68 - el_GR: 7a3cb0179636accc7bbead2387cec860c137aca0 - en_AU: 4a60d467a9115db29d4a452cde03e7996b68521e - en_CA: 99d2abbbd7fded4ae574755ddc97cf09da360316 - en_GB: 3d7f778ea0a3baaf826ae75a094d77c46410902f - en_NZ: 156b873323b7f62ff5f89712ba68a92c3b30f232 - en_PT: 9411c94aa25a77198a67282b2432407debfaff5c - eo_UY: a1ce982b6136757a26a94a0e9edd5cc25f70fba6 - es_AR: e3f3c8cce37e4c80002de874a583dcd377470df9 - es_ES: 2a256700d7cefc41926f62dc87ccb76599643ff5 - es_MX: 8d8d51e8f21260fb77581be0b2a12eed5d56766f - es_UY: bf2b7f9004c43881825705feaf3989830e4cfafa - es_VE: 968ba415ab21b0bbb8d71e2f10f2dbd100bf8820 - et_EE: 1c90a5d1ca1b99608561b281155c275e5680cbb5 - eu_ES: 2b627ce813e32f8109ae1057f3278228ffa880b9 - fa_IR: f3f8bb89b5ce3d8a905458f0faa52a54d1034515 - fi_FI: c3b57c938a7c104818c41da39b5a4301efd44b18 - fil_PH: e967b3ff8a7cc9cc00c31c78e2b1546a3a714459 - fo_FO: 96c3798fd2d9fc97bb149a743bf0cdc0d628888a - fr_CA: a9b0ad3b674db9f7ab8a0e3a4b8ec1321e362aa3 - fr_FR: c12f2e63231e761700694081d39aa47b0d533605 - fy_NL: 3c15e260908b120968318dcd08e49cbdb9ac5a6c - ga_IE: 519ae2ab660d1be7ae3016b36e549756de44a4e6 - gl_ES: 32fa7eb363deb2236d4860d793f3ec675c9957b0 - gv_IM: 4d42a28e578e1fb12f4744172e2092c49f43c900 - he_IL: 78cde0b439b284ae5f70c99ef3205d17aa6a84c2 - hi_IN: 56f50d77326eccfdc0cef4f8c0aee6cd8b64c592 - hr_HR: 29770e9eb516e30d4bca4eec9b940bff510b8019 - hu_HU: 1080b78a5519638a4f55b3fb44f135987bbb57b0 - hy_AM: 749f64d5f1172262b8a1454cf840723a1a2324b3 - id_ID: df62bdd871b031b18c9fcdfe5712cbe68e90d14c - is_IS: a180039046138fc3fef028fcb0b1788ed08cafdf - it_IT: 53c3c820a18efd12bb7ba47ac1e7bbb8b132e914 - ja_JP: 04d0398e572d1748f244b0d1b8bb394cbdc0e10d - jbo_EN: d60621bfc18f7894f0c347c6d506fb63616bd954 - ka_GE: 9c192e806f8ba6731605643d7a1e3699483da2f6 - ko_KR: 88b0c38cf3d048219c7e77d5a19d6f3d7766a004 - ksh_DE: 05b1b223d95f15b3daf49045cb541bb1e09f3eed - kw_GB: 46b97f55efc0a8b84b6a087cf3c1b43f4852d0ee - la_LA: f9ba1cef4a53b5754093fc95fc437088e80c6801 - lb_LU: 4af118fe44866a2b9c004b309a4c7f1f046a78d8 - li_LI: 7d3116dbbe5aba04c561dbb94f6999dc4c48261f - lol_US: 459fe36088664addb7e4bae5efb713b3cd140dd4 - lt_LT: f69fe1c79ba3785056f3919c797bd4085c8782ef - lv_LV: 764a8b81a077b3bb5b6fbb8d2095c0a477615a68 - mi_NZ: ff44d81edc912844b5853a8c47c4572a5a85f6b7 - mk_MK: e36871b054123e621f662c479ba750b8632eb88e - ms_MY: 0ee82caaf2422488d98c9ef5c88369196b0d5730 - mt_MT: dc17b2866256b389110401b25ee63c9f20d2b618 - nds_DE: a5f6e36080aca58e4783c447c4edeb3b6f863080 - nl_NL: 073e0c235d82141e80514f5acf695d00f90e45fb - nn_NO: 4142115f19ff598ff2dbb244e6be2e16456db460 - no_NO: cf43fe3a34ea8a58ce0f502c22176a778c275248 - oc_FR: 9256715f6ee6ce94c9a3f0c20030c97cbd45af56 - pl_PL: 901f3f4b37beb880ac0e163ae13d8573d3f84cc7 - pt_BR: dfd5789c529993030c3f3b086eefa4f7bf3adf6c - pt_PT: a33c505875e52c9910d11a50c1c59e26889c0693 - qya_AA: 3127d68e0b566d392cda30f1e0b21467c212cd58 - ro_RO: ebb521ff5a34f7a288a8d0a48567b77d450a9410 - ru_RU: 6c3bedbc74fd3c1a69eb93dbcc1a364a4feadb00 - se_NO: dc80ab3aee3ee1952cdddc5b00c5e0563cd38678 - sk_SK: 524c11924cffb2c9e4f56827ed57acd249561002 - sl_SI: cc68d238846e309a0f01c477f02575e11e25c5b7 - so_SO: aebe1285c23e89b882140f06798376dcb650c9d3 - sq_AL: 36c7d9dbf645069c12947be5e533ebec5fe755f1 - sr_SP: 6896d07c4d8574191b95194cd20fc9c718713405 - sv_SE: 10ff0bb5b5de999781549ac11a7c6fe8ac35129e - th_TH: 3b8ea299730f40e2727621dae9fe241f7ed07248 - tlh_AA: 3de07ce04b8848062727941def06295240321bec - tr_TR: 57e1a01ec4bba6690b3f3eda47d13307168e1578 - tzl_TZL: 252d5ecf33ba12dadcbe8c9ff24570cd43dc226e - uk_UA: 18132173863993eb8b12b9b7a1658ad48291ac4d - val_ES: 3c3aca77c2dd6f7b5ea568ff2fb393596d40ea69 - vi_VN: 34c0b39e65c6acad82f99318a5f643a2cf3703b8 - zh_CN: ab63cd4945a0656f9debf1326516e372c6af4cba - zh_TW: 799a1a6d3a2acf887ad20d9e97a72f6f5791be8c -'1.10': - ga_IE: a108f19142820b3573a658d40950ba3317b65c15 - fr_CA: 723c4b7b38e8b6b31f4553839b39dbd012bb8ffb - nl_NL: 438dc4b9f088959e1f4d166043cf346960b528f4 - he_IL: 5d6f158f979aaa16a9012087dbaefdfe984c5297 - en_CA: ceba29e0180c4beebbb1484321e0bcbf29f98f99 - fr_FR: 5a59c36cbec04e8ef76114d8f0741adad56774e9 - en_GB: 3afa6f85bf8c67b6cc64e31eac0641167621332e - la_LA: 44e5e1c9a3b9be21e1d9bb7701eb7867ea86bb9b - jbo_EN: 7454fb4cd01da93bed0f68bc120a5dd1ab28f2fc - vi_VN: 23ff883e1247f64d5d277845dc82c5a6e098d42c - ko_KR: 82b686b4167dfcd51e74e86678dd1288f00946c8 - es_ES: 8fef0137bb86d722969ce6a0f28068c6966bd270 - et_EE: 77c3304346537e89d0db012882dbadd9898129a2 - gv_IM: 53aa59ca42939a3b9909a9203982714372009e9b - gd_GB: ffd64edfa980396483a269372da3373c4549c066 - be_BY: 50e02b1f8447b36347163434fc7bc040c951f79d - ksh_DE: ab3798916fbf2cc600b6344c6aae73bf3bc5e1de - en_UD: 58a1bc041e9d53ce2df613c6cda42704a2140e20 - el_GR: 555e4a25e1475a93ac0ee013b27e163a526af227 - hr_HR: 492d956ebc33a0c1404c131c36a3ecd6ef7164da - en_PT: 0216bd823b1a6fa25bcd790193e1919e2e867062 - kw_GB: 880f37229dc57562c362e117cf65e26e24eef350 - en_AU: 7155181a9d8548a2ab3e8efceb34c83425e1fe0c - fi_FI: e311a2604ea666a526cc75969ad8eeb300ea943b - gl_ES: e322e3e94e87aeb9c89f78ed807c9652a326856b - pl_PL: cb6b9f7f5dfceb26ce817817de4f2f4d1dd0e5d0 - it_IT: 44fa43059018cecf291b7431f43c6a980d0fcc95 - bg_BG: ea61f16d9ff63c63bc75022c4a98c4f28e1cc874 - se_NO: dc80ab3aee3ee1952cdddc5b00c5e0563cd38678 - cs_CZ: 403cf3ac9df665e7febb5c3bc958dd4c0c0179d5 - hi_IN: bab0a7ab4f1ee230b78f74a3371996b194ef1652 - qya_AA: 338ec96b51281a579b35a62f79f4f7a3cf6ff207 - tr_TR: 277d7a60c78507bdccbdf251cef39f6da86d0e61 - hy_AM: 84de86041757281c8b996df4d45b6276d5dac508 - tlh_AA: ccf8d1f3b509bc3d37ec9ef62846da2a6354b1d9 - lt_LT: d42a1a7831668d32c911d4d8e4ab4bcc50b5606b - tzl_TZL: 0e988ca8d9386215aa71a7addf5ce46eedf29707 - es_MX: b1a7ff6fe8e6bc0ad9bbecc20442d0e81eae667c - ka_GE: e6bf16a27c48e567e9701bb51c2c690aff756b93 - da_DK: ad67f2cf303be487d71e31b6a0712b16c91225cf - uk_UA: 52037cc9f50cd842757ef0fa00b537ac02469e5f - es_AR: 7f2e7353569e98fc736298361a8d03c0a159e10c - hu_HU: 42ced8533a3a9d828d91fdf73d6f3eb053d597a2 - mi_NZ: b4bdef5baafeebb36e6c9ab16f317f0790853ac2 - ca_ES: 2f20d46550c614ac6b23c2290ed3c6e50d0e5fbb - ru_RU: 4e32e955eee6653cc052d03e75435bdc88b0b9e3 - sr_SP: 410770b892938c1a946da28671164896788390cd - eu_ES: ffa2b54f069468e6ce23c89bd51a49137bb93ee9 - sq_AL: d1e06155c50a3ee5b035647c6804c2b7b80be974 - th_TH: c63f9db60ecc45b61863425da8e7bc2051b04291 - is_IS: 6a14719ddcaa1bfcecde5503209a0229f430ea93 - val_ES: 29a8624f1227f25db78ae62fcc8d151a63330946 - lb_LU: 6a5e0375fe1dfd107d0880a0a10a79c2f28eb485 - de_DE: 917d0d7a4e18ba3d57dc6cf9aee785ff0e8323f4 - pt_BR: aec8042cfd618fa98f3fe9b02106aa33d00ea2fb - oc_FR: 764f2a42a6aa45cf57c6092e8eb5e48b24d7fc78 - so_SO: 7ed677597c2c5b9ded5445fd815b3a1798a1390f - sv_SE: b2563a5e5a809c5fa148c56a0e223589bb22f3b7 - fy_NL: 8afdadc20dfed781cd5117984940f0860e4223f0 - no_NO: e6ac65581910343ab4756eb46d5bc237a5a107eb - id_ID: d5996be276985b3b599881e309359c4b46c127d5 - mk_MK: c3224726f97d43ab866ec6a33ae66dc54be1f983 - br_FR: cdf6683552b79c64fbb95c4f5bc6fe3b86108915 - eo_UY: 3f3761f322955532ab68636ad6d7088f8711bb5c - sl_SI: 98d3e76f4ee1d46f66eabb24de5149aa71eb84bb - fo_FO: 5e72b1a677c89c024d737791ae417ad63c7abc61 - ar_SA: ae863f71f491338581311eb2e73b49699b32da62 - pt_PT: aaed9ed84bf53067db1e0d88efc393d59e8ffac2 - li_LI: fcef0f0a2c4863fe60f3686a2313182602a0083f - ms_MY: 6b66ae4928984942c3d85b0139df2bff3ac4145f - ast_ES: 5625eb95ba347535c41ecdfb0f165b1449a26e45 - lv_LV: 1c0c4991d64d8416998a980b23a340d60eeeb21b - es_UY: 9bb5e510eb83ea4877f645194c5afeb4df86d1ca - nn_NO: 0d794180a022a8fbd526e5c1fbaad924b260940f - ro_RO: 6af118fa4007dad7522db513711026ccf26951ba - mt_MT: 31a9cdfc35ddd03bd3929663a6ced4c8c2255a3b - es_VE: b83c230da6c7d01928f25f52697484362f72c259 - fil_PH: c6306cba286fb3a9a66524e2a05cb6c402c99290 - lol_US: 79da71600352237822c9f9b6f4c08e3b591e88ee - af_ZA: 9205d2b3fcd1d5484fc8975eb03427a291c579a1 - jp_JP: a2c7e6f12038c17a4f821413972e6e17cad47801 - en_NZ: a3647529aa09ed731a10de6be22ba2316f5afad1 - fa_IR: 720e4fbe100100d629e3afe2483b0d21f23ac9d9 - zh_CN: fdf080609fddf827b36e7095293c9a1732108e98 - cy_GB: ecad36e8362623f3f6d45f11fec19061cdeead41 - zh_TW: d1ddbda6e2265bb41587f65919d9fa538635fd83 - az_AZ: 80ab9060187a210b82ab9436d10a67d090f39871 - nds_DE: 871cbdb86c70b0dbc77a82d75311dab081d40532 - sk_SK: 417d5a22c64b1d4c594fb9e4d5ba0ac1c29b9bf6 -'1.11': - de_AT: af8b9e0bb5ba670ac2f74cb2f26b6c3d57408f88 - br_FR: c8646b8b84ffcce5eef697d6be7fed75039fc601 - ro_RO: 61be38a4c3a424b9e81c1948b032710048e0d69b - af_ZA: 95e45a792e6862d98104674dcd44470e29a3f9db - mt_MT: da4a6d6a99520fed7c47097dcf87a988615501eb - pt_BR: 1e6c824bef0e9aa3669608221562703e3105182e - th_TH: 70bbc37bc5bc46b88f3df5e0df37268c0875568c - io_IDO: 1a35e8d2958bcb5ca47770228b9cfe68b14c7d3d - cs_CZ: 1474c25d71fbccda764c590aed1973dca714b60e - hu_HU: c298ca23bcb2d96f19b1468847c6aaaef3154bbc - ca_ES: f3c3bf4dc5e837e11ce3d72853995497f0744e7a - ar_SA: 73a059e9cfb54340b2066f8bc01aa7a127b3363a - es_UY: 0b71aabd31177bf5ce55009ed4dc6be00337d38b - gl_ES: 241dde9742904efab4ebb4c3db9dd6cdc26c827a - kw_GB: 664135d9c2b59260b780dfe9fb07540175b79817 - gv_IM: b04fa8d09c2f7704f7a986041520fd44ff3f9cac - so_SO: d79930046547eda548449fadca1032ebf4858a87 - en_PT: 21bb6aae1458a02ad2168c727b293a4ca420a3d8 - es_MX: 7ba2f702d30a42b6ecd8762a8fe075e54cc14520 - sk_SK: 77f77e04dc33a70dc98f04d28508d2bb52260336 - eo_UY: 5e07644fdab5df2b218c4124dc296abc8c27357f - es_ES: 06923d1a4ef314a805c916572b32c1267f6396e8 - ast_ES: 108702defa6b861054770766dbd8c3b4c5e117fb - nl_NL: 2f0343b1ef80afe53ae468440c2a0143432aca88 - is_IS: 38a57d737de4c35cac5c6df13f5df47de780d897 - es_VE: 603419f761fd0931eeaac4d67ba7b379a38dee43 - sq_AL: e5f7cc83d2074de0e91901c742eff97d9f0f5dae - sv_SE: 93021118c7841c4cf3db33e600f269d4109a57f9 - es_AR: 030dd9f0a615aa2bf4a4f72486766bce6da2bcad - en_UD: 86253d1e55398161d0357d44a295231887ed4638 - gd_GB: d5c86dd44c8c5159bb4129fc38c34e813bd3a665 - da_DK: a519fd64cc6f3131781f0b55d32b24a3ac0febff - fo_FO: 2fa6782a593bcfd93365d88e43f7795b844499fc - hr_HR: bba04a3fe79f8b285ceecd1883f58ad81c4310a5 - sr_SP: a391065e81ccf1004a35ef9ce2a56a6fadfae1b1 - ko_KR: f989724019cf84675b86dc42af00cffe413f70f3 - lt_LT: e1b5220db9f79e7520a2fc6b63408a23adb501c4 - ksh_DE: 1791cdcfd0252f0c9d104a8351c922f90ca7aa80 - no_NO: 2969dbad901c25720a62e7cff3c15726563eab14 - it_IT: e1715d04a52334f78aa05137897f7f065e79dcbf - el_GR: 96063abecd6a7da5169baa83e4e62976d042cf93 - ru_RU: df2ef74c90ac6c443b3957b6f3b38d96447b5b80 - pl_PL: 97c0d4385e3e60b86ca362e16209dab703e6f982 - swg_DE: 3fc9c739eac860b28d23fc79eae27c7f716a735a - be_BY: 7fb77fae7598ed19c55bdf841306fc8b6253732d - en_AU: 34504d3b968e43111e3a33d34ae2f71d9bb596ee - tr_TR: 2edaeff5a612d44b4d628f6a310120f29786447f - hi_IN: 3f7cd670e9708455de68e1f813ccbb3db3b5edb5 - id_ID: 800d6a4ade6b71d4082f8fb54b1479b09e60673b - jbo_EN: 084c87157b2039dc12a0e1b87ab31949c79ccb1e - qya_AA: 31ae4161eae0a73bdfec68deb8957921224490c7 - mn_MN: ca573f459203895acc19aa817169b282120a98b1 - he_IL: 8e5505cf90f9a3f7a8c74d34584a500f9e88b651 - fr_FR: f49222c05a387d5607acaf30258459e4d00d28e6 - tzl_TZL: 9efbae62a84e4c2fb113ec1861dc0c501b8e9e71 - se_NO: 950ab22a148005000136b49bcd59b1caa03f6ce8 - ja_JP: 5861259da07c3284978ed16be32542e8ae074383 - lol_US: 71c6b7510b94bd74631f9e045bdb733cda1fe13a - de_DE: b603384aef84cb3a7b0faa4bc4af966ca69aa890 - ms_MY: eb0c9eb0b098cacc2fb697d560bc833b1c23e73d - zh_TW: 4b7346ba280c18b60b66c041d81e1856ed3dc335 - eu_ES: 4016544298fb6bb8948652b0585d0ca8959fe1fe - haw_US: 53a0862dd93a971f863f2007af8bd14ec273a62a - tlh_AA: ced5c58bcfee8ce7d8b2ec3025513ba5fb635be8 - li_LI: 03e880f8d9e99b6ea57d861fd5546f722723258c - oc_FR: 929a30df6a50a4cf4246002b4630b8c025dce997 - la_LA: c74566c1df2b72f6a3ac105942ec40bde3f34a65 - en_NZ: 2dacae405c58351e8e45ddbac35825f00d720f05 - nn_NO: 5fe18baa7c3cb1e6a7c71df73b4ca569663381cf - fr_CA: d865b5ec55ef44aa79ed1ba0750abf180cff1cfc - fil_PH: 6a81e6536085213cec29aa34d5a525d7ebe6532c - fa_IR: 0d1db33a369cd94d1c631910a7ada6aa7f011c0a - nds_DE: f027adfb478798c67e57e1420719cc2b4a84906b - val_ES: 27d7fbd61755deba9520f7f860d3651bb17ec2e1 - bg_BG: 8dad615c8a9c32fe33b264925fa62465c51abc40 - vi_VN: d9dff14b5e9ac3f6c0dfa7b83dbccf3cc6d274c1 - hy_AM: 9a58b202573061de32c863f8ae604d2d9fc08114 - lb_LU: 1ac7fcb6f6b42588ed58ccd9efd4a5ce76ad5cf1 - mk_MK: b79da5855ce5f8a6d0d722fb0f89602dddfb283f - cy_GB: c25f7affa9fb462319b69b8abfb0174d264f67ae - az_AZ: d5bc9e6039c31d63fcaebc7d80a5340d83cb2fc5 - fi_FI: 8be617fdf0e8daecd2690426c87b15c617b73339 - en_GB: d0aef6a924a0c2a3153611e7ce76e78e33880fc1 - et_EE: e01f6f40a0d1d3949a55230a3168fe8ac373578c - ka_GE: cadffa7a950b0cf516a280319b96a1f0ab3a55b0 - en_CA: 31a16f9cf5640c2ec553407369eea60eead749bf - uk_UA: 08d7d8d8930b3707b23cef81b45e573625016faf - lv_LV: 0912c2eaa5cfaf464f9ea90be2beb256fd96f14f - ga_IE: afc4e411f6b77f096c4f994ebf1c3efec29b3aec - sl_SI: b58e6457c2a69e7093d5aab784fdc263b72e139d - zh_CN: f67425f55bf27981de5acaa964e0f92a4218d0cb - mi_NZ: c6ff33b29951b8e70cf99c4ebed0c6c6424dd65b - pt_PT: a2e7085634ddcc644dc5918463030c7d4b9dae6b - fy_NL: c9d02a40667ce9d8252d4af3618faaa71422f7e2