Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong detected locale in a brazilian portuguese OS #272

Closed
renato opened this issue Apr 22, 2015 · 6 comments
Closed

Wrong detected locale in a brazilian portuguese OS #272

renato opened this issue Apr 22, 2015 · 6 comments

Comments

@renato
Copy link

renato commented Apr 22, 2015

Using another LAF, Java used the corrent pt-BR Locale automatically.

However, using WebLAF, when the LanguageManager initializes, it detects the "portuguese" translation and resets the Locale to only "pt", breaking some internationalization details (ie. the "¤" in number patterns translating to "€" instead of "R$").

If necessary, I can provide the changes to a pt-BR translation, but I think it would still be a problem for other similar situations.

@mgarin
Copy link
Owner

mgarin commented May 5, 2015

WebLaF uses custom translation files provided for each supported language, supported languages can be found as constants in com.alee.managers.language.LanguageConstants class.


So far there weren't any variations for single language, but I guess this is the case with pt and pt-BR. So far I'm not sure what is the best solution - either to provide a completely separate translation XML file for pt-BR or just add a smart way to vary some of its parts depending on the variation.

For example here is how part of translation XML looks like right now:

<Dictionary name="Web Look and Feel language" prefix="weblaf" author="Alee Software" creationDate="27.04.2012">
    <Dictionary name="Library information frame" prefix="info">
        <record key="title">
            <value lang="en">Library information</value>
            <value lang="ru">Информация о библиотеке</value>
            <value lang="pl">Informacje o bibliotece</value>
            <value lang="ar">معلومات عن البرنامج</value>
            <value lang="es">Información de la Librería</value>
            <value lang="fr">Information sur la bibliothèque</value>
            <value lang="pt">Inflormação sobre a biblioteca</value>
            <value lang="de">Bibliotheksinformationen</value>
            <value lang="it">Informazioni sulla Libreria</value>
            <value lang="tr">Kütüphane bilgisi</value>
        </record>
        <Dictionary name="General information tab" prefix="general">
            <record key="title">
                <value lang="en">General</value>
                <value lang="ru">Общие</value>
                <value lang="pl">Ogólny</value>
                <value lang="ar">عام</value>
                <value lang="es">General</value>
                <value lang="fr">Général</value>
                <value lang="pt">Geral</value>
                <value lang="de">Allgemein</value>
                <value lang="it">Generale</value>
                <value lang="tr">Genel</value>
            </record>
        </Dictionary>
    </Dictionary>
    <LanguageInfo>
        <langInfo lang="en" author="mgarin" info="English" title="English" />
        <langInfo lang="ru" author="mgarin" info="Russian" title="Русский" />
        <langInfo lang="pl" author="sciepa" info="Polish" title="Polski" />
        <langInfo lang="ar" author="Abu Abdullah" info="Arabic" title="العربية" />
        <langInfo lang="es" author="pablovilas" info="Spanish" title="Español" />
        <langInfo lang="fr" author="movierenamer" info="French" title="Français" />
        <langInfo lang="pt" author="esimoes" info="Portuguese" title="Português" />
        <langInfo lang="de" author="trashguru" info="German" title="Deutsch" />
        <langInfo lang="it" author="cR0Ck" info="Italian" title="Italiano" />
        <langInfo lang="tr" author="Tilelook" info="Turkish" title="Turkish" />
    </LanguageInfo>
</Dictionary>

So my point is that a completely new translation can be added under pt-BR key:
(I have removed other languages to highlight only meaningful parts)

<Dictionary name="Web Look and Feel language" prefix="weblaf" author="Alee Software" creationDate="27.04.2012">
    <Dictionary name="Library information frame" prefix="info">
        <record key="title">
            <value lang="pt">Inflormação sobre a biblioteca</value>
            <value lang="pt-BR">Informações sobre a biblioteca</value>
        </record>
        <Dictionary name="General information tab" prefix="general">
            <record key="title">
                <value lang="pt">Geral</value>
                <value lang="pt-BR">Geral</value>
            </record>
        </Dictionary>
    </Dictionary>
    <LanguageInfo>
        <langInfo lang="pt" author="esimoes" info="Portuguese" title="Português" />
        <langInfo lang="pt-BR" author="renato" info="Portuguese" title="Brazilian Português" />
    </LanguageInfo>
</Dictionary>

Or some changes can be made in LanguageManager to support language variations if there are any for the case. Here is an example how that could look like in XML:

<Dictionary name="Web Look and Feel language" prefix="weblaf" author="Alee Software" creationDate="27.04.2012">
    <Dictionary name="Library information frame" prefix="info">
        <record key="title">
            <value lang="pt">Inflormação sobre a biblioteca</value>
            <value lang="pt-BR">Informações sobre a biblioteca</value>
        </record>
        <Dictionary name="General information tab" prefix="general">
            <record key="title">
                <value lang="pt">Geral</value>
            </record>
        </Dictionary>
    </Dictionary>
    <LanguageInfo>
        <langInfo lang="pt" author="esimoes,renato" info="Portuguese" title="Português" />
    </LanguageInfo>
</Dictionary>

In the first case - languages will be considered as completely separate and will have no connection to each other. So even if there are just a few symbols difference between pt and pt-BR a complete translation must be provided for both of them.

In the second case (with some modifications added to LanguageManager) language variations might be applied according to language suffix, -BR in this specific case. Basically - you will need to fill-in pt language translation and can add suffix-related changes which will be used if according language is selected. For example if simply pt was chosen as language - translations with prefix will simply be ignored, if pt-BR was selected pt-BR-marked values will have priority over pt-marked values.

I guess second case might be a better choice to reduce size of language file and simplify it.


Also about:

However, using WebLAF, when the LanguageManager initializes, it detects the "portuguese" translation and resets the Locale to only "pt", breaking some internationalization details (ie. the "¤" in number patterns translating to "€" instead of "R$").

This might be happening for the same reason I described in the beginning - WebLaF doesn't know anything about language variations so if you set it to use LanguageConstants.PORTUGUESE language (or it detects it on its own) it will also set default Locale in your application and that affects how various stuff that uses Locale works (like patterns I guess).

So this should also be fixed as soon as variations are considered by WebLaF.

@mgarin mgarin added this to the v1.30 milestone May 5, 2015
@mgarin mgarin self-assigned this May 5, 2015
@renato
Copy link
Author

renato commented May 5, 2015

The common solution is to have an entirely different translation, AFAIK. Anyway, the other solution is great too.

The real problem here is that, IMHO, it should be possible to use the portuguese translation with a pt-BR locale, which I don't think is possible, currently. And "pt vs pt-BR" being just an example, there are certainly other countries/languagues that will suffer from the same situation.

@mgarin
Copy link
Owner

mgarin commented May 5, 2015

I totally agree on this one, that is why I offered the second solution.

It will have a bit more to it (just noticed that I didn't mention that) - it will actually allow you to set translation AND its variation if it is required.

As an example, even if WebLaF only supports base pt translation and you need pt-BR - you can still use it and have appropriate pt-BR locale set. And LanguageManager will simply use base pt translation in that case. But in addition to that - if -BR variations are added in translation for some keys - those will be replacing base pt translation.

So it should be simple-to-use in general.

To summ up - you will only need to use (as an example):

LanguageManager.setLanguage ( LanguageConstants.PORTUGUESE_BR );

to setup pt-BR if it is supported by WebLaF or simply:

LanguageManager.setLanguage ( "pt-BR" );

and even if there are no values for -BR variation this will still be valid if WebLaF supports base language (which is pt in this example).

Same will work for other cases like:

LanguageManager.setLanguage ( "en-GB" );
LanguageManager.setLanguage ( "en-US" );

And of course you will still be able to use base (or general) translation:

LanguageManager.setLanguage ( "en" );

@mgarin
Copy link
Owner

mgarin commented May 5, 2015

So I think I will go with the second solution, it should be pretty easy to add, but will provide a good improvement to translation system overall.

@mgarin mgarin modified the milestones: v1.29, v1.30 May 5, 2015
@mgarin
Copy link
Owner

mgarin commented Oct 31, 2017

It's been quite a while since I've started working on this one, but today I'm finally at the point where I can post an update on the upcoming changes.

Initially I wanted to do a small pass over the LanguageManager to add a few features including this one, but it ended up as a major revamp that took quite some time.

So, what have changed?


  1. Proper Locale support

LanguageManager now uses Locale instead of the String language code and will no longer ignore your country choice.

Here is an example of an XML dictionary that uses country codes within its values:

<Dictionary name="WebLaF test dictionary" prefix="weblaf.test">

    <!-- Dictionary with country-related record -->
    <Dictionary prefix="country">
        <record key="record1">
            <value lang="en">English</value>
            <value lang="en-US">US English</value>
            <value lang="en-GB">GB English</value>
            <value lang="ru">Русский</value>
        </record>
        <record key="record2">
            <value lang="en">Other record</value>
            <value lang="ru">Другая запись</value>
        </record>
    </Dictionary>

</Dictionary>

You might notice that I didn't include en-US and en-GB in the second record, but you will still get translation done right even if you have either en-GB or en-US set as the LanguageManager locale.

Basically values without country codes will be used as a fallback. Values with country code can also be used as a fallback but they will have lowest priority when picked. So if you are requesting en-GB translation priority will be: en-GB > en > en-US


  1. Multiple languages accessible simultaneously

One of the biggest changes coming with the update is possibility to access multiple languages at the same time. Basically you can now request "en", "en-US", "ru", "pt-BR" or any other translations without touching global language stored within LanguageManager.

It is achieved by using separate instances of Language class which basically only keeps Locale within itself and provides you with a full set of methods to access any translations.

Global translations (for language currently selected within LanguageManager) can now be acquired through LM class which by default uses Language instance stored within LanguageManager. You can also modify the static Supplier for Language instance within LM to provide any Language instances you want for global usage. That can be handy if, for instance, you want your Language to be tied to Thread context (we used that approach with one of our web applications already).

LanguageManager API have been changed and it doesn't provide any methods to access translations anymore to avoid any confusion. Also internal structure of Dictionary have been completely redesigned and it now contains multiple internal caches for providing quick access to any records across multiple nested dictionaries.

So let's say we have a dictionary like this one:

<Dictionary name="WebLaF test dictionary" prefix="weblaf.test">

    <!-- Simple record -->
    <record key="record">
        <value lang="en">English</value>
        <value lang="en-US">US English</value>
        <value lang="ru">Русский</value>
    </record>

</Dictionary>

This is how we will access default (current language) translation:

final String text = LM.get ( "weblaf.test.record" );

This is how we will access en translation directly:

final Language en = new Language ( new Locale ( "en" ) );
final String text = en.get ( "weblaf.test.record" );

This is how we will access en-US translation directly:

final Language enUS = new Language ( new Locale ( "en", "US" ) );
final String text = enUS.get ( "weblaf.test.record" );

And this is how we will access ru translation directly:

final Language ru = new Language ( new Locale ( "ru" ) );
final String text = ru.get ( "weblaf.test.record" );

As you might have noticed - we have created quite a few Language instances there, but worry not, there is no overhead there as the only thing Language stores within itself is the Locale you want to request translations for. So you are free to create any amount of Language instances without consuming excessive amounts of memory or processing time.

Simultaneous access to different languages might not be highly useful for desktop application cases since most commonly you have a single language for your UI, but it is extremely useful for some niche cases.


  1. Default Locale is not forcefully updated anymore

I agree that this was a bad design choice as it did break quite a few things for some specific cases of Locale usage in various applications, so I finally got rid of this code within LanguageManager along with providing appropriate Locale support.

LanguageManager does not change default JVM Locale by default anymore. But if you liked that feature and want to get it back - you can use a special LanguageListener implementation:

LanguageManager.addLanguageListener ( new LanguageLocaleUpdater () );

This will simply update default JVM Locale with the one set in LanguageManager.


  1. Proper separation between core and ui manager parts

While I always call it LanguageManager - there are actually two main classes that represent language implementation in WebLaF - widely known LanguageManager.java and barely ever mentioned WebLanguageManager.java. The latter was never really used because it never had any functionality to begin with, it only registered some LanguageUpdater implementations related to ui module.

But it will completely change now, WebLanguageManager will now have a big chunk of features which were initially tied to LanguageManager. To be more specific - all features related to UI. With that change I will finally able to untie core LanguageManager from Swing and eventually separate it into language module - just as it was mentioned in #336 issue.

For now module core will still include basic LanguageManager and will include basic translation options. But features like LanguageUpdaters and component-related LanguageListeners will now be in ui module within WebLanguageManager.

I have also made an additional pass through all Web-components to add missing bridge methods for WebLanguageManager so that you can use them directly on the component.


  1. Proper translation support for lists, combobox, tables and trees

Lists, comboboxes, tables and trees are quite problematic components when it comes down to translating their content. It might be easy to provide translation as values and within nodes, but updating the components appropriately upon any language changes can be quite difficult.

This is why LanguageSensitive interface was added to assist you. Simply implement it in your custom list, combobox, table or tree, any of their renderers or in the data objects used as values or nodes - components will automatically update themselves if something changes within LanguageManager.

Just make sure to return new translation whenever cell value or node value is requested. That simple.

You can check ExamplesTree in DemoApplication - it does exactly that. You can also switch language in demo and that tree will properly update its node sizes.


  1. Tooltips in Value have been replaced with Text usage

Object Tooltip have been removed. It can now replaced with Text object with three possible states:

  • tooltip - Provides tooltip text, tooltip type will be decided by the library
  • swing-tooltip - Provides tooltip text for common Swing tooltip
  • custom-tooltip - Provides tooltip text for custom WebLaF tooltip

Options TooltipType type, TooltipWay way and Integer delay that were previously available in Tooltip object are removed and no longer available. Default tooltip delay can be configured for all tooltips within TooltipManager, but default tooltip direction will always be determined by library.

If you have any tooltips in your custom dictionaries, for instance:

<Dictionary prefix="sample">
    <record key="tip">
        <value lang="en">
            <text>Hover to see tooltip</text>
            <tooltip>Simple text within JToolTip popup</tooltip>
        </value>
        <value lang="ru">
            <text>Наведите для просмотра подсказки</text>
            <tooltip>Простой текст внутри JToolTip попапа</tooltip>
        </value>
    </record>
</Dictionary>

You might want to replace them with something like this:

<Dictionary prefix="sample">
    <record key="tip">
        <value lang="en">
            <text>Hover to see tooltip</text>
            <text state="tooltip">Simple text within JToolTip popup</text>
        </value>
        <value lang="ru">
            <text>Наведите для просмотра подсказки</text>
            <text state="tooltip">Простой текст внутри JToolTip попапа</text>
        </value>
    </record>
</Dictionary>

If you want to provide some deeper customization for your tooltips - you can do that through a custom LanguageUpdater or through explicitly specifying a custom tooltip with a separate language code, but it is not possible anymore within translations.

This is a reasonable limitation I had to add to avoid LanguageManager interacting with UI code in the core module.


  1. Mnemonic have been moved from Value to Text

Since there are multiple Text instance you can provide for different state within a single Value it is reasonable to have a separate mnemonic for each Text as the actual translation may vary between different Texts.

Here is a simple example of how it was before:

<Dictionary name="WebLaF test dictionary" prefix="weblaf.test">

    <!-- Old mnemonics -->
    <record key="button">
        <value lang="en" mnemonic="S">
            <text>Select me</text>
            <text state="selected">Release me</text>
        </value>
    </record>

</Dictionary>

And how it works now:

<Dictionary name="WebLaF test dictionary" prefix="weblaf.test">

    <!-- Stateful mnemonics -->
    <record key="button">
        <value lang="en">
            <text mnemonic="S">Select me</text>
            <text state="selected" mnemonic="R">Release me</text>
        </value>
    </record>

</Dictionary>

Of course binding specific states to UI element states is up to developer, but mnemonics can now be properly integrated into different states of the same component if needed.


  1. Hotkeys are not available within Value anymore

On initial LanguageManager release I tried to push as many features as possible to try them out on actual projects and see which ones will prove to be useful and stay and which will not be widely used and can eventually be removed.

Unfortunately hotkeys are one of the things I decided to exclude from LanguageManager for a few reasons:

  • Too obscure
  • Hard to customize
  • Unrelated to the translations in general (unlike the mnemonic)

And there is also one more reason - there is already a HotkeyManager which should be used for defining hotkeys and shouldn't delegate its work to the other manager. Although its current implementation has a few issues and I am working on fixing them and bringing some additional heavy improvements to it as well.


  1. Memory and performance optimizations

Previously LanguageManager always stored a separate massive cache of all records added through various registered Dictionarys. That cache generation took some precious processing time at application startup and also used a chunk of memory even if translations were never even requested once.

There were also a few technical issues with updating old caches - you might have noticed that sometimes, if Dictionarys were modified in runtime the cache would still keep old translations.

Well, it's completely different story now - caches are stored within each separate Dictionary instance and only generated on demand whenever some record or translation is requested. All caches are now also properly updated upon any changes within the Dictionary itself. There have been quite a few challenges with this new system I had to overcome, but the result was certainly worth it.


These are the major changes coming soon (will be dropping this update in next 2-3 days). There will also be a lot of other minor fixes, tweaks and improvements to other parts of the library coming along.

mgarin added a commit that referenced this issue Nov 8, 2017
`LanguageManager` was changed to allow requesting translations for multiple languages simultaneously and also to provide full support for any country codes. Big changes have also been made to features available within core `LanguageManager` and its UI counterpart - `WebLanguageManager`. Manger API was also slightly improved to reflect the changes.

JUnit tests
With this commit I have added first two JUnit tests for `LanguageManager` and `Merge` as the most intricate things within the library so far (not counting `StyleManager` but it will surely be covered later as well). I intend to add more tests in the future to cover most complicated library parts and make sure no major issues are going into any branches.

Language
- LanguageManager.java - Doesn't contain any UI-related code anymore, those have been moved into `WebLanguageManager` class
- LanguageManager.java - Doesn't change locale according to provided language anymore [ #272 #457 ]
- LanguageLocaleUpdater.java - `LanguageListener` implementation that can be used to auto-update default `Locale` with `LanguageManager` one
- Language.java - New class providing access to translations based on `Locale` it stores, multiple instances provide access to multiple languages
- LM.java - Reworked to provide convenient access to default `Language` instance or any other `Language` that is provided by customizable supplier
- LanguageListener.java - Now only provides `Language` change event instead of being all-in-one listener
- DictionaryListener.java - Now provides all `Dictionary`-related events instead of `LanguageListener`
- LanguageConstants.java - Removed as redundant, all/supported locales can now be properly requested from `LanguageManager`
- Dictionary.java - Removed `author`, `creationDate` and `notes` fields as redundant
- Dictionary.java - Now contains all transient record and dictionary caches within itself
- Dictionary.java - Renamed `languageInfos` into `translations` to reflect its actual meaning
- Dictionary.java - Added methods to retrieve "all" and "fully supported" locales
- TranslationInformation.java - Renamed from `LanguageInfo` and refactored
- TranslationInformation.java - Language replaced with `locale` field to allow using country codes (ex. `en-GB` or `en-US`)
- TranslationInformation.java - Removed `info` field as redundant
- LanguageMethods.java - Now added to all existing Web-components as it can properly apply tooltip-only translations
- JTextComponentLU.java - Now detects `IInputPrompt` interface usages in component or UI to provide translation for it
- WebTextFieldLU.java, WebPasswordFieldLU.java, WebFormattedTextFieldLU.java - Removed as redundant
- WebAbstractButtonLU.java - Removed as redundant, `AbstractButtonLU` fulfills its role now
- WebLanguageUpdater.java - Removed as redundant as hotkeys are not supported by `LanguageManager` anymore
- LanguageUpdaterSettings.java - Removed as a bad settings design, configuration remains within `JTabbedPaneLU`
- LanguageSensitive.java - New marker interface created to assist UI components with detecting language-sensitive content
- ListPainter.java, TreePainter.java, TablePainter.java - Updated to react to language-sensitive component, models, renderers and data
- language.xml - Have been replaced with separate `core`, `ui` and `demo` XML dictionaries [ #470 ]
- core-language.xml - New XML dictionary for `core` module
- ui-language.xml - New XML dictionary for `ui` module
- demo-language.xml - New XML dictionary for `demo` module
- en_GB.png, en_US.png - New language variation icons

LanguageChooser
- LanguageChooser.java - New customizable language chooser based on supported `LanguageManager` locales
- LanguageChooserModel.java - Provides a list of supported or predefined locales
- languagechooser.xml - Separate light and dark styles for `LanguageChooser`

HeatMap
- HeatMap.java - New UI debugging tool that paints rendering time heat map over the UI

Tree
- TreeWalker.java - New interface providing options to conveniently iterate `JTree` nodes
- AbstractTreeWalker.java - Abstract `TreeWalker` containing implementations for basic methods
- SimpleTreeWalker.java - `TreeWalker` implementation for simple trees like `JTree`, `WebTree` and `WebExTree`
- AsyncTreeWalker.java - `TreeWalker` implementation for `WebAsyncTree` that contains some workarounds
- TreeUtils.java - Added method to retrieve `TreeWalker` implementation compatible with provided `JTree`

Renderers
- WebListCellRenderer.java, WebTreeCellRenderer.java, WebTableCellRenderer.java - Fixed performance issues for disabled icons
- WebListCellRenderer.java, WebTreeCellRenderer.java - Added hover decoration state support

Components
- Added missing implementations for `ContainerMethods`, `EventMethods` and `ToolTipMethods`

Style
- StyleId.java, ComponentStyle.java - Expanded complete style identifier to avoid style caches overwriting each other
- StyleManager.java, StyleData.java - Fixed a critical issue that might break skins loading order
- MovingHighlightBackground.java - Added appropriate cleanup on deactivation, optimized and refactored code
- MenuItemLayout.java - It is now more flexible and can be applied to any component, not just `JMenuItem`
- RoundRectangle.java - Fixed preferred size calculation

ComboBox
- WebComboBoxModel.java - Replacement for default `DefaultComboBoxModel` with generic item type and additional methods
- ComboBoxPainter.java - Removed redundant font and background updates from painting methods
- WebComboBoxRenderer.java - Added new `pressed`, `expanded` and `collapsed` states for renderer component

MenuItem
- AbstractMenuItemLayout.java - Contains most of the code previously stored in `MenuItemLayout`
- MenuItemLayout.java - Only includes `JMenuItem`-related features now
- SimpleMenuItemLayout.java - New simplified menu item layout that is not tied to `JMenuItem` type and can be used separately

DocumentPane
- WebDocumentPane.java - Added "select" option for document open methods to allow choosing whether or not opened document tab should be selected
- PaneData.java, ui-language.xml - Added "Close all" menu option for all tabs

DateField
- WebDateFieldUI.java - Added "Escape" hotkey for closing calendar popup

Collection duplicate resolver
- DuplicateResolver.java - Base interface for any class that detects and resolves duplicates within any `Collection`
- AbstractDuplicateResolver.java - Abstract `DuplicateResolver` containing some basic methods for usage convenience
- IgnoreDuplicates.java, RejectDuplicates.java, RemoveDuplicates.java - Basic `DuplicateResolver` implementations
- DuplicateException.java - Special exception type used within `DuplicateResolver` implementations

Object matcher
- Matcher.java - Base interface for any kinds of object matchers
- AbstractMatcher.java - Abstract `Matcher` that uses generic types for matched objects
- EqualMatcher.java, IdentifiableMatcher.java, SkippingMatcher.java - Basic `Matcher` implementations

Merge
- ListMergeBehavior.java - Have been greatly improved and made configurable with `Matcher` and `DuplicateResolver` usage
- IndexListMergeBehavior.java - New simple list elements merge behavior for index-to-index merge
- Overwriting.java - Now implements `Mergeable` by default
- RelativeTypeMergePolicy.java - Renamed from `RelatedTypeMergePolicy` for convenience
- Mergeable.java, GlobalMergeBehavior.java - Minor JavaDoc improvements

Clone
- Clone.java - Added minor improvement to allow `Clone` to set final values

API
- BiPredicate.java - `BiPredicate` from JDK8 for later porting convenience

DemoApplication
- DemoApplication.java - Added `HeatMap` tool
- Updated multiple classes according to code changes

LibraryInfoDialog
- LibraryInfoDialog.java - Refactored and cleaned up code, moved styles into extension
- LibraryInfoExtension.java, LibraryInfoIconSet.java - Extension and icon set for `LibraryInfoDialog`
- info-extension.xml, info-icons.xml, java.svg - Resources for `LibraryInfoDialog`

Utilities
- ImmutableSet.java - New unmodifiable `Set` implementation
- IconUtils.java - New utility class providing methods for various icon manipulations
- FileUtils.java - Added method to filter out unwanted symbols from text for file name
- ArrayUtils.java - Added methods to compare arrays
- CollectionUtils.java - Added method to retrieve maximum element from collection according to comparator

Project
- pom.xml - Updated to include JUnit library as test dependency
- build.properties - Updated path to `LibraryInfoDialog`
- Added currently used JUnit library version and its dependencies
@mgarin
Copy link
Owner

mgarin commented Nov 8, 2017

All changes mentioned above (and actually a few more) are now available in styling branch.

Going back to issue question - default locale chosen by LanguageManager will now take system country settings into account. Default Locale will not be touched anymore unless you use this code:

LanguageManager.addLanguageListener ( new LanguageLocaleUpdater () );

And you can now also set Locale as language base into LanguageManager instead of simple string, which allows you to specify country properly and it will also be taken into account when translations are selected.

@mgarin mgarin closed this as completed Nov 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants