Panduan untuk Kumpulan Sumber

1. Gambaran keseluruhan

Banyak pembangun perisian, sepanjang kerjaya profesional mereka, menghadapi peluang untuk mengembangkan sistem atau aplikasi pelbagai bahasa. Ini biasanya ditujukan untuk pengguna akhir dari pelbagai kawasan atau kawasan bahasa yang berbeza.

Selalu mencabar untuk mengekalkan dan memperluas aplikasi ini. Keupayaan untuk beroperasi dengan pelbagai data penyetempatan pada masa yang sama biasanya sangat penting. Pengubahsuaian data aplikasi semudah mungkin tanpa memerlukan penyusunan semula. Itulah sebabnya kita biasanya mengelakkan label atau nama butang yang dikodkan keras.

Nasib baik, kita dapat menggunakan Java yang menyediakan kelas ini kepada kita, yang dapat membantu kita menyelesaikan semua masalah yang disebutkan di atas.

Ringkasnya, ResourceBundle membolehkan aplikasi kami memuat data dari fail berbeza yang mengandungi data khusus tempat.

1.1. Kumpulan Sumber

Perkara pertama yang harus kita ketahui ialah semua fail dalam satu kumpulan sumber mesti berada dalam pakej / direktori yang sama dan mempunyai nama asas yang sama . Mereka mungkin mempunyai akhiran khusus bahasa yang menunjukkan bahasa, negara, atau platform yang dipisahkan oleh simbol garis bawah.

Penting untuk kita menambahkan kod negara jika sudah ada kod bahasa, atau platform jika bahasa dan kod negara ada.

Mari lihat contoh nama fail:

  • Contoh Sumber
  • ContohResource_en
  • ContohResource_en_US
  • ContohResource_en_US_UNIX

Fail lalai untuk setiap kumpulan data selalu satu tanpa akhiran - Contoh Sumber . Oleh kerana terdapat dua subkelas ResourceBundle : PropertyResourceBundle dan ListResourceBundle , kita secara bergantian dapat menyimpan data dalam fail harta tanah dan juga fail java.

Setiap fail mesti mempunyai nama khusus tempat dan sambungan fail yang betul , sebagai contoh, ExampleResource_en_US.properties atau Example_en.java .

1.2. Fail Hartanah - PropertyResourceBundle

Fail harta tanah diwakili oleh PropertyResourceBundle. Mereka menyimpan data dalam bentuk pasangan nilai kunci peka huruf besar-kecil.

Mari kita analisis contoh fail harta tanah:

# Buttons continueButton continue cancelButton=cancel ! Labels helloLabel:hello 

Seperti yang kita lihat, ada tiga gaya berbeza untuk menentukan pasangan nilai-kunci.

Semuanya setara, tetapi yang pertama mungkin yang paling popular di kalangan pengaturcara Java . Perlu diketahui bahawa kita juga boleh meletakkan komen dalam fail harta tanah. Komen selalu bermula dengan # atau ! .

1.3. Fail Java - ListResourceBundle

Pertama sekali, untuk menyimpan data khusus bahasa kita, kita perlu membuat kelas yang memanjangkan ListResourceBundle dan mengatasi kaedah getContents () . Konvensyen nama kelas adalah sama seperti untuk fail harta tanah.

Untuk setiap Lokasi , kita perlu membuat kelas Java yang berasingan.

Berikut adalah kelas contoh:

public class ExampleResource_pl_PL extends ListResourceBundle { @Override protected Object[][] getContents() { return new Object[][] { {"currency", "polish zloty"}, {"toUsdRate", new BigDecimal("3.401")}, {"cities", new String[] { "Warsaw", "Cracow" }} }; } }

Fail Java mempunyai satu kelebihan utama berbanding file properti yang merupakan kemungkinan untuk menahan objek yang kita inginkan - bukan hanya Strings.

Sebaliknya, setiap pengubahsuaian atau pengenalan kelas java khusus lokal baru memerlukan penyusunan semula aplikasi sedangkan fail harta tanah dapat diperluas tanpa usaha tambahan.

2. Gunakan Kumpulan Sumber

Kami sudah tahu bagaimana menentukan kumpulan sumber, jadi kami bersedia menggunakannya.

Mari pertimbangkan coretan kod pendek:

Locale locale = new Locale("pl", "PL"); ResourceBundle exampleBundle = ResourceBundle.getBundle("package.ExampleResource", locale); assertEquals(exampleBundle.getString("currency"), "polish zloty"); assertEquals(exampleBundle.getObject("toUsdRate"), new BigDecimal("3.401")); assertArrayEquals(exampleBundle.getStringArray("cities"), new String[]{"Warsaw", "Cracow"});

Pertama, kita dapat menentukan Lokal kita , kecuali kita tidak mahu menggunakan yang lalai.

Selepas itu, mari kita panggil kaedah kilang statik ResourceBundle . Kita perlu memberikan nama kumpulan dengan pakej / direktori dan lokasi sebagai parameter.

Terdapat juga kaedah kilang yang hanya memerlukan nama kumpulan jika lokasi lalai adalah baik. Sebaik sahaja kami mempunyai objek, kami dapat mengambil nilai dengan kunci mereka.

Selain itu, contoh menunjukkan bahawa kita boleh menggunakan getString (String key) , getObject (String key), dan getStringArray (String key) untuk mendapatkan nilai yang kita mahukan.

3. Memilih Sumber Bundle yang Betul

Sekiranya kita ingin menggunakan sumber bundle, penting untuk mengetahui bagaimana Java memilih fail bundle.

Mari kita bayangkan bahawa kita bekerja dengan aplikasi yang memerlukan label dalam bahasa Poland tetapi lokasi JVM lalai anda adalah Locale.US .

Pada mulanya, aplikasi akan mencari fail di classpath yang sesuai dengan tempat yang anda minta. Dimulai dengan nama yang paling spesifik, iaitu, yang mengandungi platform, negara, dan bahasa.

Kemudian, ia menjadi lebih umum. Sekiranya tidak ada perlawanan, ia akan kembali ke lokasi lalai tanpa pemeriksaan platform kali ini.

Sekiranya tidak sesuai, ia akan cuba membaca kumpulan lalai. Segala-galanya harus jelas ketika kita melihat urutan nama fail yang dipilih:

  • Label_pl_PL_UNIX
  • Label_pl_PL
  • Label_pl
  • Label_en_US
  • Label_en
  • Label

Kita harus ingat bahawa setiap nama mewakili kedua-dua .java dan .properties fail, tetapi bekas mengambil lebih dahulu dari yang kedua. Apabila tidak ada fail yang sesuai, MissingResourceException akan dilemparkan.

4. Warisan

Another advantage of the resource bundle concept is property inheritance. It means that key-values pairs included in less specific files are inherited by those which are higher in the inheritance tree.

Let's assume that we have three property files:

#resource.properties cancelButton = cancel #resource_pl.properties continueButton = dalej #resource_pl_PL.properties backButton = cofnij

Resource bundle retrieved for Locale(“pl”, “PL”) would return all three keys/values in the result. It's worth to mention, there's no fall back to default locale bundle as far as property inheritance is considered.

What is more, ListResourceBundles and PropertyResourceBundles aren't in the same hierarchy.

So if a property file is found in the classpath then key-value pairs are inherited only from property files. The same rule applies to Java files.

5. Customization

All we've learned above was about the default implementation of ResourceBundle. However, there's a way we can modify its behavior.

We do this by extending ResourceBoundle.Control and overriding its methods.

For example, we can change the time of keeping values in cache or determine the condition when the cache should be reloaded.

For a better understanding, let's prepare a short method as an example:

public class ExampleControl extends ResourceBundle.Control { @Override public List getCandidateLocales(String s, Locale locale) { return Arrays.asList(new Locale("pl", "PL")); } }

The purpose of this method is to change a manner of selecting files in the classpath. As we can see, ExampleControl will return only polish Locale, no matter what the default or defined Locale is.

6. UTF-8

Since there're still many applications using JDK 8 or older versions, it's worth to know that prior to Java 9ListResourceBundles had one more advantage over PropertyResourceBundles. As Java files can store String objects, they are able to hold any character supported by UTF-16 encoding.

On the contrary, PropertyResourceBundle loads files by default using ISO 8859-1 encoding, which has fewer characters than UTF-8 (causing problems for our Polish language examples).

In order to save characters which are beyond UTF-8, we can use the Native-To-ASCII converter – native2ascii. It converts all characters that aren't compliant with ISO 8859-1 by encoding them to \uxxxx notation.

Here's an example command:

native2ascii -encoding UTF-8 utf8.properties nonUtf8.properties

And let's see how properties look like before and after a change of encoding:

#Before polishHello=cześć #After polishHello=cze\u015b\u0107

Fortunately, this inconvenience exists no longer in Java 9. JVM reads property files in UTF-8 encoding, and there's no problem in using non-Latin characters.

7. Conclusion

BundleResource contains much of what we need to develop a multilingual application. The features we've covered make manipulation of different locales pretty straightforward.

Kami juga mengelakkan hardcoding nilai, membolehkan kita untuk mengembangkan disokong Locales dengan hanya menambah baru Locale fail membenarkan permohonan kami untuk lancar diubahsuai dan dikekalkan.

Seperti biasa, contoh kod tersedia di GitHub.