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

WIP: Support MessageBundles as properties #651

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions manifold-deps-parent/manifold-properties-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,33 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.27.0</version>
<scope>test</scope>
</dependency>
</dependencies>


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
* limitations under the License.
*/

import junit.framework.TestCase;
import static org.assertj.core.api.Assertions.*;

/**
*/
public class DefaultPackageTest extends TestCase
import org.junit.jupiter.api.Test;

class DefaultPackageTest
{
public void testDefaultPackage()
@Test
void testDefaultPackage()
{
assertEquals( "value1", DefaultPackageProps.Value1.toString() );
assertEquals( "sub", DefaultPackageProps.Value1.Sub );
assertThat( DefaultPackageProps.Value1 ).hasToString( "value1" );
assertThat( DefaultPackageProps.Value1.Sub ).hasToString( "sub" );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@

package manifold.api.properties;

import junit.framework.TestCase;
import static org.assertj.core.api.Assertions.*;

import abc.MyProperties;
import gw.lang.SystemProperties;
import org.junit.jupiter.api.Test;

/**
*/
public class PropertiesTest extends TestCase
class PropertiesTest
{
public void testProperties()
@Test
void testProperties()
{
assertEquals( "Hello", MyProperties.MyProperty.toString() );
assertEquals( "Sub Property", MyProperties.MyProperty.Sub );
assertNotNull( SystemProperties.java.version );
assertThat( MyProperties.MyProperty ).hasToString( "Hello" );
assertThat( MyProperties.MyProperty.Sub ).hasToString( "Sub Property" );
assertThat( SystemProperties.java.version ).isNotNull();
}

public void testFragrment()
@Test
void testFragment()
{
//[MyPropertiesRightHere.properties/] Foo=bar
assertEquals( "bar", MyPropertiesRightHere.Foo );
assertThat( MyPropertiesRightHere.Foo ).hasToString( "bar" );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2019 - Manifold Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package manifold.api.properties;

import static org.assertj.core.api.Assertions.*;
import java.util.Locale;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junit.platform.commons.util.ReflectionUtils;
import resourcebundle.Message;
import resourcebundle.Message2;
import resourcebundle.Message3;

class ResourceBundleTest
{

/**
* Tests the default values for the message bundle 'resourcebundle.Messages' when the default locale is used.
*/
@Test
void testMessagesDefault()
{
assertThat(Message.getLocale()).isEqualTo(Locale.ROOT);
assertThat(Message.foo).hasToString("foo");
assertThat(Message.App.Hello).hasToString("Hello");
assertThat(Message.foo.bar.test).hasToString("bar");
assertThat(Message.getValueByName("foo.bar.test")).hasToString("bar");
assertThat(Message.foo.getValueByName("bar.test")).hasToString("bar");
}

/**
* Tests the localized values for the message bundle 'resourcebundle.Messages'.
* Verifies that the values are correctly localized based on the provided language tag.
*
* @param languageTag The language tag to test.
*/
@ParameterizedTest
@ValueSource(strings = {"nl", "nl-BE", "nl-NL", "fr-FR", "fr-FR-POSIX"})
void testMessagesLocalized(String languageTag)
{
Locale locale = Locale.forLanguageTag(languageTag);
Message.setLocale(locale);

assertThat(Message.getLocale()).isEqualTo(locale);
assertThat(Message.foo).hasToString("foo_" + languageTag);
assertThat(Message.App.Hello).hasToString("Hello_" + languageTag);
assertThat(Message.foo.bar.test).hasToString("bar_" + languageTag);
assertThat(Message.getValueByName("foo.bar.test")).hasToString("bar_" + languageTag);
assertThat(Message.foo.getValueByName("bar.test")).hasToString("bar_" + languageTag);
}

/**
* Verifies that when an exact match for the message bundle and the locale does not exist,
* the most specific values are used instead.
*
*/
@Test
void testMessagesLocaleDoesNotExistVariant()
{
Message.setLocale(Locale.forLanguageTag("nl-BE-POSIX"));

assertThat(Message.getLocale()).isEqualTo(Locale.forLanguageTag("nl-BE"));
assertThat(Message.foo).hasToString("foo_nl-BE");
assertThat(Message.App.Hello).hasToString("Hello_nl-BE");
assertThat(Message.foo.bar.test).hasToString("bar_nl-BE");
assertThat(Message.getValueByName("foo.bar.test")).hasToString("bar_nl-BE");
assertThat(Message.foo.getValueByName("bar.test")).hasToString("bar_nl-BE");
}

/**
* Verifies that when no match for the message bundle and the locale exist,
* the default values are used instead.
* */
@Test
void testMessagesLocaleDoesNotExistLocale()
{
Message.setLocale(Locale.forLanguageTag("fr"));

assertThat(Message.getLocale()).isEqualTo(Locale.ROOT);
assertThat(Message.foo).hasToString("foo");
assertThat(Message.App.Hello).hasToString("Hello");
assertThat(Message.foo.bar.test).hasToString("bar");
assertThat(Message.getValueByName("foo.bar.test")).hasToString("bar");
assertThat(Message.foo.getValueByName("bar.test")).hasToString("bar");
}

/**
* Tests the default values for another message bundle ('resourcebundle.Message2').
* Verifies that the default values are as expected when using the second message bundle.
*/
@Test
void testMessagesDefaultSecondMessageBundle()
{
assertThat(Message2.m2.foo).hasToString("foo");
assertThat(Message2.m2.App.Hello).hasToString("Hello");
assertThat(Message2.m2.foo.bar.test).hasToString("bar");
}

/**
* Tests the values for a message bundle that has only the default locale available ('resourcebundle.Message3').
* This uses the normal properties logic.
*/
@Test
void testMessagesWithOnlyDefaultMessageBundleAvailable()
{
assertThat(Message3.m3.foo).hasToString("foo");
assertThat(Message3.m3.App.Hello).hasToString("Hello");
assertThat(Message3.m3.foo.bar.test).hasToString("bar");
assertThat(Message3.m3.getValueByName("foo.bar.test")).hasToString("bar");
assertThat(Message3.m3.foo.getValueByName("bar.test")).hasToString("bar");

// verifies that 'setLocale' method does not exist
assertThat(ReflectionUtils.findMethod(Message3.class, "setLocale", Locale.class)).isEmpty();
// verifies that 'getLocale' method does not exist
assertThat(ReflectionUtils.findMethod(Message3.class, "getLocale")).isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello
foo=foo
foo.bar.test=bar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
m2.App.Hello=Hello
m2.foo=foo
m2.foo.bar.test=bar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
m2.App.Hello=Hello_de
m2.foo=foo_de
m2.foo.bar.test=bar_de
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
m3.App.Hello=Hello
m3.foo=foo
m3.foo.bar.test=bar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello_fr-FR
foo=foo_fr-FR
foo.bar.test=bar_fr-FR
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello_fr-FR-POSIX
foo=foo_fr-FR-POSIX
foo.bar.test=bar_fr-FR-POSIX
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello_nl
foo=foo_nl
foo.bar.test=bar_nl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello_nl-BE
foo=foo_nl-BE
foo.bar.test=bar_nl-BE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App.Hello=Hello_nl-NL
foo=foo_nl-NL
foo.bar.test=bar_nl-NL
24 changes: 24 additions & 0 deletions manifold-deps-parent/manifold-properties/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ Behind the scenes the properties type manifold creates a Java class for the prop
hierarchy of properties. As you develop your application, changes you make in the file are immediately available in
your code with no user intervention in between -- no code gen files and no compiling between changes.

This can also be used for `MessageBundles`.
Unlike regular properties, an additional `setLocale` method is generated,
enabling you to dynamically change the locale.

`resources/abc/messages.properties`:
```properties
hello = Hello
test.foo = Foo
```
`resources/abc/messages_fr.properties`:
```properties
hello = Bonjour
test.foo = Bar
```

```java
println(abc.messages.hello); // prints "Hello"
println(abc.messages.test.foo); // prints "Foo"
abc.messages.setLocale(Locale.forLanguageTag("fr")); // change locale to French
println(abc.messages.hello); // prints "Bonjour"
println(abc.messages.test.foo); // prints "Bar"
```


# IDE Support

Manifold is fully supported in [IntelliJ IDEA](https://www.jetbrains.com/idea/download) and [Android Studio](https://developer.android.com/studio).
Expand Down
Loading