Skip to content

Languages

I-Al-Istannen edited this page Oct 13, 2016 · 12 revisions

Languages

This library contains a small language system. At the time of writing it consists of two classes:

  1. MessageProvider
  2. I18N

MessageProvider

This interface is used to abstract most of the workings of the language, so you can easily change the implementation. Sadly only true to an extend, as the copyDefaultLanguages method is defined in I18N, as this is an interface. But I digress.

Methods

The methods are all commented with Javadoc. Not much to add.

I18N

This class is a bit more fun. It uses Java's I18N inside.

Methods

The only methods visible to you outside the package should be the ones defined by the superinterface. Everything else should be considered a poor choice, maybe a bug and should be done better before anything burns down.

Construction

This is a bit trickier. It requires a few things:

  1. Locale currentLanguage
  2. String basePackage
  3. Path savePath
  4. ClassLoader callerClassLoader
  5. Category defaultCategory
  6. Category... more

I will tackle them one by one.

  1. This is the language it should use
  2. This is the path to the package where all language files are in
  3. This is the path to the directory where the files should be saved, for the user to be editable.
  4. This is the ClassLoader of the caller. It is needed to be able to access the guts of another jar file.
  5. This is the default category to use.
  6. These are more categories.

Now you may have a few questions: "the package where all language files are in"? What are language files? Why a package??

Well, let me explain this.

Prerequisites:

  • A package with your language files. Just a plain old java package
  • Language files. This are files ending on ".proprties". They normally consist of three parts:
    1. The "Category" (It is the name. I renamed it. Sue me.)
    • This can be anything. It is just an identifier to make it possible for you to find it. A typical name could be "Messages".
    1. The language
    • This is the part that tells the system which language is inside the file. It has the following format: Category_<language tag>.properties. The language tag for english is "en". So that would be "Messages_en.properties". If you are from Germany, it could be as specific as "Messages_de_DE.properties". There can be pretty much anything, as long as there is a locale for it.
    1. And ".properties"
    • A simple extension.

So your project could look like this: ``` main `- java `- `- resources `- language `- Messages_en.properties `- Messages.properties ```

The Messages.properties is special. It is a fallback. Every language will eventually end up redirecting here. So having a <Category>.properties file ensures that every possible language will be translated, even if it fallbacks to the language in there. Always provide it, probably in english.


A lookup looks first in the appropiate language file and then moves closer to `.properties` as it doesn't find a key. So defining it in a more general save file will make it availlabe to all children, without redefining it. This can reduce the file size of the more special languages.
### Usage:

Once you set it up, you can just use one of the method prefixed with "tr" to translate a key. To translate a key called "Test_key" and to color the message that is there, use I18N#tr("Test_key", <Category or blank for default>);.


**Cooler aspects of the Usage**
  1. Variables
    It can replace variables. Yay. They have a special format: {<index>}. An example is {0}. So consider the following language file:
    not_enough_money= You are too broke. Sorry. You only have {0} and need {1}.
    Now, if you translate it, you can pass two extra arguments:
    I18N#tr("not_enough_money", <Category or blank for default>, 65.66, 89.02425);
    This will print "You are too broke. Sorry. You only have 65.66 and need 89.02425".

Not really pretty, is it? You might say this is unfair, I inputed ugly numbers. Truth is a double or float isn't nice. But we can do better! `not_enough_money= You are too broke. Sorry. You only have {0,number,$ #.##} and need {1,number,$ #.##}.` This will print: "You are too broke. Sorry. You only have $ 65.66 and need $ 89.02" A lot better, right?
"number" tells it it is a number and let's you specify a normal `DecimalFormat` pattern. See [here](https://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html) for all possibilities.
  1. Reference
    As of @Rayzr's request you can cross-reference.
    So if you have the two keys
    Key_one= This is key one
    Key_two= This is key two
    You can add a third key:
    Key_three= [[Key_one]] says "[[Key_two]]"

The result? `This is key one says "This is key two"`
Replacing a variable **doesn't** work in referenced keys.
  1. Multi line
    If you want a multi-line value, you can use the "\n" escape sequence. If you want that the value spans multiple lines in your editor, add a backslash at the end of the line:
this.is.a.key= This is a multiline \n \
key \n \
And another
Clone this wiki locally