Skip to content

ICU-22124 Adding a tech preview implementation of MessageFormat v2 #2170

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

Merged
merged 1 commit into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions icu4j/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,7 @@
<packageset dir="${icu4j.core.dir}/src">
<include name="com/ibm/icu/lang/**"/>
<include name="com/ibm/icu/math/**"/>
<include name="com/ibm/icu/message2/**"/>
<include name="com/ibm/icu/number/**"/>
<include name="com/ibm/icu/text/**"/>
<include name="com/ibm/icu/util/**"/>
Expand Down Expand Up @@ -1396,6 +1397,7 @@
<packageset dir="${icu4j.core.dir}/src">
<include name="com/ibm/icu/lang/**"/>
<include name="com/ibm/icu/math/**"/>
<include name="com/ibm/icu/message2/**"/>
<include name="com/ibm/icu/number/**"/>
<include name="com/ibm/icu/text/**"/>
<include name="com/ibm/icu/util/**"/>
Expand Down Expand Up @@ -1442,6 +1444,7 @@
<packageset dir="${icu4j.core.dir}/src">
<include name="com/ibm/icu/lang/**"/>
<include name="com/ibm/icu/math/**"/>
<include name="com/ibm/icu/message2/**"/>
<include name="com/ibm/icu/number/**"/>
<include name="com/ibm/icu/text/**"/>
<include name="com/ibm/icu/util/**"/>
Expand Down Expand Up @@ -1646,6 +1649,7 @@
<packageset dir="${icu4j.core.dir}/src">
<include name="com/ibm/icu/lang/**"/>
<include name="com/ibm/icu/math/**"/>
<include name="com/ibm/icu/message2/**"/>
<include name="com/ibm/icu/number/**"/>
<include name="com/ibm/icu/text/**"/>
<include name="com/ibm/icu/util/**"/>
Expand All @@ -1668,6 +1672,7 @@
<packageset dir="${icu4j.core.dir}/src">
<include name="com/ibm/icu/lang/**"/>
<include name="com/ibm/icu/math/**"/>
<include name="com/ibm/icu/message2/**"/>
<include name="com/ibm/icu/number/**"/>
<include name="com/ibm/icu/text/**"/>
<include name="com/ibm/icu/util/**"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

package com.ibm.icu.message2;

import java.util.Locale;
import java.util.Map;
import java.util.Objects;

import com.ibm.icu.impl.locale.AsciiUtil;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;

/**
* Creates a {@link Formatter} doing formatting of date / time, similar to
* <code>{exp, date}</code> and <code>{exp, time}</code> in {@link com.ibm.icu.text.MessageFormat}.
*/
class DateTimeFormatterFactory implements FormatterFactory {

private static int stringToStyle(String option) {
switch (AsciiUtil.toUpperString(option)) {
case "FULL": return DateFormat.FULL;
case "LONG": return DateFormat.LONG;
case "MEDIUM": return DateFormat.MEDIUM;
case "SHORT": return DateFormat.SHORT;
case "": // intentional fall-through
case "DEFAULT": return DateFormat.DEFAULT;
default: throw new IllegalArgumentException("Invalid datetime style: " + option);
}
}

/**
* {@inheritDoc}
*
* @throws IllegalArgumentException when something goes wrong
* (for example conflicting options, invalid option values, etc.)
*/
@Override
public Formatter createFormatter(Locale locale, Map<String, Object> fixedOptions) {
DateFormat df;

// TODO: how to handle conflicts. What if we have both skeleton and style, or pattern?
Object opt = fixedOptions.get("skeleton");
if (opt != null) {
String skeleton = Objects.toString(opt);
df = DateFormat.getInstanceForSkeleton(skeleton, locale);
return new DateTimeFormatter(df);
}

opt = fixedOptions.get("pattern");
if (opt != null) {
String pattern = Objects.toString(opt);
SimpleDateFormat sf = new SimpleDateFormat(pattern, locale);
return new DateTimeFormatter(sf);
}

int dateStyle = DateFormat.NONE;
opt = fixedOptions.get("datestyle");
if (opt != null) {
dateStyle = stringToStyle(Objects.toString(opt, ""));
}

int timeStyle = DateFormat.NONE;
opt = fixedOptions.get("timestyle");
if (opt != null) {
timeStyle = stringToStyle(Objects.toString(opt, ""));
}

if (dateStyle == DateFormat.NONE && timeStyle == DateFormat.NONE) {
// Match the MessageFormat behavior
dateStyle = DateFormat.SHORT;
timeStyle = DateFormat.SHORT;
}
df = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);

return new DateTimeFormatter(df);
}

private static class DateTimeFormatter implements Formatter {
private final DateFormat icuFormatter;

private DateTimeFormatter(DateFormat df) {
this.icuFormatter = df;
}

/**
* {@inheritDoc}
*/
@Override
public FormattedPlaceholder format(Object toFormat, Map<String, Object> variableOptions) {
// TODO: use a special type to indicate function without input argument.
if (toFormat == null) {
throw new IllegalArgumentException("The date to format can't be null");
}
String result = icuFormatter.format(toFormat);
return new FormattedPlaceholder(toFormat, new PlainStringFormattedValue(result));
}

/**
* {@inheritDoc}
*/
@Override
public String formatToString(Object toFormat, Map<String, Object> variableOptions) {
return format(toFormat, variableOptions).toString();
}
}
}
120 changes: 120 additions & 0 deletions icu4j/main/classes/core/src/com/ibm/icu/message2/FormattedMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

package com.ibm.icu.message2;

import java.text.AttributedCharacterIterator;

import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.FormattedValue;

/**
* Not yet implemented: The result of a message formatting operation.
*
* <p>This contains information about where the various fields and placeholders
* ended up in the final result.</p>
* <p>This class allows the result to be exported in several data types,
* including a {@link String}, {@link AttributedCharacterIterator}, more (TBD).</p>
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public class FormattedMessage implements FormattedValue {

/**
* Not yet implemented.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public FormattedMessage() {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public int length() {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public char charAt(int index) {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public CharSequence subSequence(int start, int end) {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public <A extends Appendable> A appendTo(A appendable) {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public boolean nextPosition(ConstrainedFieldPosition cfpos) {
throw new RuntimeException("Not yet implemented.");
}

/**
* Not yet implemented.
*
* {@inheritDoc}
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public AttributedCharacterIterator toCharacterIterator() {
throw new RuntimeException("Not yet implemented.");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

package com.ibm.icu.message2;

import com.ibm.icu.text.FormattedValue;

/**
* An immutable, richer formatting result, encapsulating a {@link FormattedValue},
* the original value to format, and we are considering adding some more info.
* Very preliminary.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public class FormattedPlaceholder {
private final FormattedValue formattedValue;
private final Object inputValue;

/**
* Constructor creating the {@code FormattedPlaceholder}.
*
* @param inputValue the original value to be formatted.
* @param formattedValue the result of formatting the placeholder.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public FormattedPlaceholder(Object inputValue, FormattedValue formattedValue) {
if (formattedValue == null) {
throw new IllegalAccessError("Should not try to wrap a null formatted value");
}
this.inputValue = inputValue;
this.formattedValue = formattedValue;
}

/**
* Retrieve the original input value that was formatted.
*
* @return the original value to be formatted.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public Object getInput() {
return inputValue;
}

/**
* Retrieve the formatted value.
*
* @return the result of formatting the placeholder.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public FormattedValue getFormattedValue() {
return formattedValue;
}

/**
* Returns a string representation of the object.
* It can be null, which is unusual, and we plan to change that.
*
* @return a string representation of the object.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
@Override
public String toString() {
return formattedValue.toString();
}
}
44 changes: 44 additions & 0 deletions icu4j/main/classes/core/src/com/ibm/icu/message2/Formatter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

package com.ibm.icu.message2;

import java.util.Map;

/**
* The interface that must be implemented by all formatters
* that can be used from {@link MessageFormatter}.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
public interface Formatter {
/**
* A method that takes the object to format and returns
* the i18n-aware string representation.
*
* @param toFormat the object to format.
* @param variableOptions options that are not know at build time.
* @return the formatted string.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
String formatToString(Object toFormat, Map<String, Object> variableOptions);

/**
* A method that takes the object to format and returns
* the i18n-aware formatted placeholder.
*
* @param toFormat the object to format.
* @param variableOptions options that are not know at build time.
* @return the formatted placeholder.
*
* @internal ICU 72 technology preview
* @deprecated This API is for ICU internal use only.
*/
@Deprecated
FormattedPlaceholder format(Object toFormat, Map<String, Object> variableOptions);
}
Loading